2018-05-09

????????????????????????????????????????????????????????????????????????????????????關(guān)于數(shù)組越界的系統(tǒng)崩潰的問題



小伙伴門經(jīng)常見到這個崩潰日志吧!! ?能不能不不讓系統(tǒng)不直接崩潰,進而影響用戶體驗!??!研究了下runtime 機制可以完美解決這個問題!讓它不會因為數(shù)組越界而崩潰,并且抓取報錯的堆棧信息~~~~???? ?個人 建議:當我們在測試環(huán)境下最好不要用這個??!因為盡量減少奔潰的問題,并修復(fù)~~~~ ?對那些已經(jīng)是正式環(huán)境下可以用一下,不會因為隱藏在深處的問題導(dǎo)致系統(tǒng)直接崩潰,進而影響用戶體驗~~~~~~同時最好能上傳報錯日志,我們可以方便找到出錯的地方并且修復(fù)! ?我們公司用的是騰訊的Bugly 框架~~感興趣的童鞋可以集成一下~~~?? ?Bugly 飛機地址~~~


數(shù)組越界再熟悉不過了



利用runtime 交換系統(tǒng)的方法 ~~~~ ? ? 實現(xiàn)思路:當我們對數(shù)組取值的時候會調(diào)用以下兩種任意的一種的方法 !那么我們可以用runtime 的機制替換掉系統(tǒng)的方法,轉(zhuǎn)換為我們自定義的方法,對自定義方法里面對數(shù)組進行判斷?。。∪绻浇缌?就拋出異常!

? ? NSArray*arr =@[@"1",@"2"];

? ? NSLog(@"%@",arr[10]); ?//這個方法就是 [arr ?objectAtIndexedSubscript : 10 ] ?的縮寫

? ? NSLog(@"%@",[arr objectAtIndex:10]);

OK 下面貼出代碼


創(chuàng)建一個NSObject 分類

.h實現(xiàn)



/**

?替換系統(tǒng)方法 所有的成員方法

?@param originalSelector 系統(tǒng)的方法

?@param swizzledSelector 自定義的方法

?@return? NO表示沒有找到該方法

?*/

+ (BOOL)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector?

{

? ? MethodoriginalMethod =class_getInstanceMethod(self, originalSelector);

? ? if(!originalMethod) {

? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類沒有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];

? ? ? ? NSLog(@"%@",string);

? ? ? ? returnNO;

? ? }

? ? MethodswizzledMethod =class_getInstanceMethod(self, swizzledSelector);


? ? if(!swizzledMethod) {

? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類沒有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(swizzledSelector)];

?? ? ? ? NSLog(@"%@",string);

? ? ? ? returnNO;

? ? }


? ? if(class_addMethod(self, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod)))

? ? {

? ? ? ? class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

? ? }else{

? ? ? ? method_exchangeImplementations(originalMethod, swizzledMethod);

? ? }

? ? return YES;

}

/**

?替換系統(tǒng)方法

?@param originalSelector 系統(tǒng)的方法

?@param iswizzleMethod YES 表示系統(tǒng)方法 為類方法 ; 表示成員方法

?@param swizzledSelector 自定義的方法

?@param iswithMethod YES 表示自定義方法 為類方法 ; 表示成員方法

?@return NO表示沒有找到該方法

*/

+ (BOOL)swizzleMethod:(SEL)originalSelector IswizzleMethod:(BOOL)iswizzleMethod? withMethod:(SEL)swizzledSelector? IswithMethod:(BOOL)iswithMethod

{?

//? class_getClassMethod? 為類方法? ? ? class_getInstanceMethod? 表示成員方法

? ? MethodoriginalMethod =? iswizzleMethod==YES?class_getClassMethod(self, originalSelector):class_getInstanceMethod(self, originalSelector);

? ? if(!originalMethod) {


? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類沒有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];


? ? ? ? NSLog(@"%@",string);


? ? ? ? returnNO;

? ? }

? ? MethodswizzledMethod = iswithMethod==YES?class_getClassMethod(self, swizzledSelector):class_getInstanceMethod(self, swizzledSelector);

? ? if(!swizzledMethod) {


? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類沒有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(swizzledSelector)];


? ? ? ? NSLog(@"%@",string);


? ? ? ? returnNO;

? ? }


? ? if(class_addMethod(self, originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod)))

? ? {

? ? ? ? class_replaceMethod(self, swizzledSelector, method_getImplementation(originalMethod), method_getTypeEncoding(originalMethod));

? ? }else{

? ? ? ? method_exchangeImplementations(originalMethod, swizzledMethod);

? ? }

? ? return YES;



}



新建個NSArray 分類 ? ?.m實現(xiàn) ??


+ (void)load

{

? ?//替換不可變數(shù)組方法 取數(shù)組下標時應(yīng)該替換 ?swizzleMethod 為系統(tǒng)的方法 ??withMethod 為自定義方法

? ? ? [objc_getClass("__NSArrayI")swizzleMethod:@selector(objectAtIndexedSubscript:)withMethod:@selector(FJL_ObjectAtIndexedSubscript:)];

? ? //替換不可變數(shù)組只有一個元素的時候

?? ? [objc_getClass("__NSSingleObjectArrayI")swizzleMethod:@selector(objectAtIndex:)withMethod:@selector(FJL_objectAtIndex:)];

? ? //替換可變數(shù)組方法 取數(shù)組下標時應(yīng)該替換

?? ? [objc_getClass("__NSArrayM")swizzleMethod:@selector(objectAtIndexedSubscript:)withMethod:@selector(FJL_mutableObjectAtIndexedSubscript:)];

? ? //替換可變數(shù)組方法

?? ? [objc_getClass("__NSArrayM")swizzleMethod:@selector(objectAtIndex:)withMethod:@selector(FJL_mutableobjectAtIndex:)];

}

- (id)FJL_objectAtIndex:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return[selfFJL_objectAtIndex:index]; //注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception==== %@", exception); //異常信息

? ? ? ? ? ? // 拋出異常方式

? ? ? ? ? ? ? // [Bugly reportException:exception];//我上傳的是騰訊的崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return[self FJL_objectAtIndex:index];?//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? }

}

- (id)FJL_mutableobjectAtIndex:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

?? ? ? ? ? // 拋出異常方式

? ? ? ? ? // ?[Bugly reportException:exception];//上報崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? }

}

- (id)FJL_ObjectAtIndexedSubscript:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

? ? ? ? ? ? // 拋出異常方式

? ? ? ? ?// ?[Bugly reportException:exception];//上報崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? }

}

- (id)FJL_mutableObjectAtIndexedSubscript:(NSUInteger)index

{

? ? if(index >self.count-1|| !self.count) {

? ? ? ? @try{

? ? ? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? ? ? }

? ? ? ? @catch(NSException *exception) {

? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);

? ? ? ? ? // ?[Bugly reportException:exception];//上報崩潰日志

? ? ? ? ? ? returnnil;

? ? ? ? }


? ? }else{

? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒有遞歸操作. 因為交換了系統(tǒng)的方法

? ? }

}

OK ?以上就是所有的源碼 ? ?用著有問題歡迎@我哈


?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,030評論 0 9
  • 轉(zhuǎn)載:http://www.cocoachina.com/ios/20161102/17920.html 因為Ob...
    F麥子閱讀 699評論 0 1
  • 轉(zhuǎn)載:http://yulingtianxia.com/blog/2014/11/05/objective-c-r...
    F麥子閱讀 827評論 0 2
  • 本文詳細整理了 Cocoa 的 Runtime 系統(tǒng)的知識,它使得 Objective-C 如虎添翼,具備了靈活的...
    lylaut閱讀 864評論 0 4
  • 我們常常會聽說 Objective-C 是一門動態(tài)語言,那么這個「動態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,319評論 0 7

友情鏈接更多精彩內(nèi)容