????????????????????????????????????????????????????????????????????????????????????關(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 飛機地址~~~

利用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 分類

/**
?替換系統(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 ?以上就是所有的源碼 ? ?用著有問題歡迎@我哈