????????????????????????????????????????????????????????????????????????????????????關(guān)于數(shù)組越界的系統(tǒng)崩潰的問(wèn)題
小伙伴門(mén)經(jīng)常見(jiàn)到這個(gè)崩潰日志吧!! ?能不能不不讓系統(tǒng)不直接崩潰,進(jìn)而影響用戶體驗(yàn)!Q┍辍!研究了下runtime 機(jī)制可以完美解決這個(gè)問(wèn)題灰瞻!讓它不會(huì)因?yàn)閿?shù)組越界而崩潰,并且抓取報(bào)錯(cuò)的堆棧信息~~~~???? ?個(gè)人 建議:當(dāng)我們?cè)跍y(cè)試環(huán)境下最好不要用這個(gè)!!因?yàn)楸M量減少奔潰的問(wèn)題,并修復(fù)~~~~ ?對(duì)那些已經(jīng)是正式環(huán)境下可以用一下,不會(huì)因?yàn)殡[藏在深處的問(wèn)題導(dǎo)致系統(tǒng)直接崩潰,進(jìn)而影響用戶體驗(yàn)~~~~~~同時(shí)最好能上傳報(bào)錯(cuò)日志余境,我們可以方便找到出錯(cuò)的地方并且修復(fù)! ?我們公司用的是騰訊的Bugly 框架~~感興趣的童鞋可以集成一下~~~?? ?Bugly 飛機(jī)地址~~~
利用runtime 交換系統(tǒng)的方法 ~~~~ ? ? 實(shí)現(xiàn)思路:當(dāng)我們對(duì)數(shù)組取值的時(shí)候會(huì)調(diào)用以下兩種任意的一種的方法 !那么我們可以用runtime 的機(jī)制替換掉系統(tǒng)的方法灌诅,轉(zhuǎn)換為我們自定義的方法芳来,對(duì)自定義方法里面對(duì)數(shù)組進(jìn)行判斷!Q铀堋绣张!如果越界了 就拋出異常答渔!
? ? NSArray*arr =@[@"1",@"2"];
? ? NSLog(@"%@",arr[10]); ?//這個(gè)方法就是 [arr ?objectAtIndexedSubscript : 10 ] ?的縮寫(xiě)
? ? NSLog(@"%@",[arr objectAtIndex:10]);
OK 下面貼出代碼
創(chuàng)建一個(gè)NSObject 分類(lèi)
/**
?替換系統(tǒng)方法 所有的成員方法
?@param originalSelector 系統(tǒng)的方法
?@param swizzledSelector 自定義的方法
?@return? NO表示沒(méi)有找到該方法
?*/
+ (BOOL)swizzleMethod:(SEL)originalSelector withMethod:(SEL)swizzledSelector?
{
? ? MethodoriginalMethod =class_getInstanceMethod(self, originalSelector);
? ? if(!originalMethod) {
? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];
? ? ? ? NSLog(@"%@",string);
? ? ? ? returnNO;
? ? }
? ? MethodswizzledMethod =class_getInstanceMethod(self, swizzledSelector);
? ? if(!swizzledMethod) {
? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類(lèi)沒(méi)有找到 %@ 方法",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)方法 為類(lèi)方法 ; 表示成員方法
?@param swizzledSelector 自定義的方法
?@param iswithMethod YES 表示自定義方法 為類(lèi)方法 ; 表示成員方法
?@return NO表示沒(méi)有找到該方法
*/
+ (BOOL)swizzleMethod:(SEL)originalSelector IswizzleMethod:(BOOL)iswizzleMethod? withMethod:(SEL)swizzledSelector? IswithMethod:(BOOL)iswithMethod
{?
//? class_getClassMethod? 為類(lèi)方法? ? ? class_getInstanceMethod? 表示成員方法
? ? MethodoriginalMethod =? iswizzleMethod==YES?class_getClassMethod(self, originalSelector):class_getInstanceMethod(self, originalSelector);
? ? if(!originalMethod) {
? ? ? ? NSString*string = [NSStringstringWithFormat:@"系統(tǒng)的: %@ 類(lèi)沒(méi)有找到 %@ 方法",NSStringFromClass([selfclass]),NSStringFromSelector(originalSelector)];
? ? ? ? NSLog(@"%@",string);
? ? ? ? returnNO;
? ? }
? ? MethodswizzledMethod = iswithMethod==YES?class_getClassMethod(self, swizzledSelector):class_getInstanceMethod(self, swizzledSelector);
? ? if(!swizzledMethod) {
? ? ? ? NSString*string = [NSStringstringWithFormat:@"自定義: %@ 類(lèi)沒(méi)有找到 %@ 方法",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;
}
新建個(gè)NSArray 分類(lèi) ? ?.m實(shí)現(xiàn) ??
+ (void)load
{
? ?//替換不可變數(shù)組方法 取數(shù)組下標(biāo)時(shí)應(yīng)該替換 ?swizzleMethod 為系統(tǒng)的方法 ??withMethod 為自定義方法
? ? ? [objc_getClass("__NSArrayI")swizzleMethod:@selector(objectAtIndexedSubscript:)withMethod:@selector(FJL_ObjectAtIndexedSubscript:)];
? ? //替換不可變數(shù)組只有一個(gè)元素的時(shí)候
?? ? [objc_getClass("__NSSingleObjectArrayI")swizzleMethod:@selector(objectAtIndex:)withMethod:@selector(FJL_objectAtIndex:)];
? ? //替換可變數(shù)組方法 取數(shù)組下標(biāo)時(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]; //注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? ? ? }
? ? ? ? @catch(NSException *exception) {
? ? ? ? ? ? NSLog(@"exception==== %@", exception); //異常信息
? ? ? ? ? ? // 拋出異常方式
? ? ? ? ? ? ? // [Bugly reportException:exception];//我上傳的是騰訊的崩潰日志
? ? ? ? ? ? returnnil;
? ? ? ? }
? ? }else{
? ? ? ? return[self FJL_objectAtIndex:index];?//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? }
}
- (id)FJL_mutableobjectAtIndex:(NSUInteger)index
{
? ? if(index >self.count-1|| !self.count) {
? ? ? ? @try{
? ? ? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? ? ? }
? ? ? ? @catch(NSException *exception) {
? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);
?? ? ? ? ? // 拋出異常方式
? ? ? ? ? // ?[Bugly reportException:exception];//上報(bào)崩潰日志
? ? ? ? ? ? returnnil;
? ? ? ? }
? ? }else{
? ? ? ? return [self FJL_mutableobjectAtIndex:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? }
}
- (id)FJL_ObjectAtIndexedSubscript:(NSUInteger)index
{
? ? if(index >self.count-1|| !self.count) {
? ? ? ? @try{
? ? ? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? ? ? }
? ? ? ? @catch(NSException *exception) {
? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);
? ? ? ? ? ? // 拋出異常方式
? ? ? ? ?// ?[Bugly reportException:exception];//上報(bào)崩潰日志
? ? ? ? ? ? returnnil;
? ? ? ? }
? ? }else{
? ? ? ? return [self FJL_ObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? }
}
- (id)FJL_mutableObjectAtIndexedSubscript:(NSUInteger)index
{
? ? if(index >self.count-1|| !self.count) {
? ? ? ? @try{
? ? ? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? ? ? }
? ? ? ? @catch(NSException *exception) {
? ? ? ? ? ? NSLog(@"exception====: %@", exception.reason);
? ? ? ? ? // ?[Bugly reportException:exception];//上報(bào)崩潰日志
? ? ? ? ? ? returnnil;
? ? ? ? }
? ? }else{
? ? ? ? return [self FJL_mutableObjectAtIndexedSubscript:index];??//注意:此處并沒(méi)有遞歸操作. 因?yàn)榻粨Q了系統(tǒng)的方法
? ? }
}
OK ?以上就是所有的源碼 ? ?用著有問(wèn)題歡迎@我哈