????????在我們項(xiàng)目的實(shí)際開發(fā)過程中,我們數(shù)據(jù)處理時經(jīng)常會遇到由于人為或不可預(yù)知的行為,使一個值變?yōu)閚il,這時候我們將這個值添加到數(shù)組或者字典中去,后果是災(zāi)難性的。一下崩潰日志相信大多數(shù)小伙伴都遇到過:

很明顯,這是一個像可變數(shù)組中嘗試添加元素的操作,可是此元素為nil,引起了崩潰。由此也引發(fā)了我們的思考,可否通過某種方法,規(guī)避掉這種崩潰。
1、向可變數(shù)組,字典中添加元素,進(jìn)行if()else判斷
????????這個方法不是不可以,但是對于一個項(xiàng)目來說,每次添加進(jìn)行判斷,是不科學(xué)的。代碼進(jìn)行了太多的重復(fù)性,意義低下的邏輯。
2、利用Object-C運(yùn)行時的特點(diǎn),當(dāng)系統(tǒng)運(yùn)行調(diào)用這個函數(shù)的時候我們可否進(jìn)行一些操作。
????????下面我們就來看一下。首先從表面上看,應(yīng)該是可以做到的具體如何做呢。首先我們給NSMutableArray建立一個分類。并引入#import <objc/runtime.h>。(本來想傳圖片,但是不知為何,上傳不了。。。。上代碼吧!?。。?/p>
#import "NSMutableArray+Extension.h"
#import <objc/runtime.h>
@implementationNSMutableArray (Extension)
+ (void)load
{
? ? ClassarrayMClass =NSClassFromString(@"_ _NSArrayM");(這里是_ _NSArraysM,參考上圖崩潰日志中-[__NSArrayM insertObject:atIndex:]這里牽扯到類簇的知識,感興趣的小伙伴自行g(shù)oole ----^_^-----)。
? ? MethodaddObject =class_getInstanceMethod(arrayMClass,@selector(addObject:));
? ? //獲取我們自定義添加元素的方法
? ? MethodnewAddObject =class_getInstanceMethod(arrayMClass,@selector(newAddObject:));
? ? //將兩個方法進(jìn)行交換 (交換方法后:當(dāng)你調(diào)用方法1,實(shí)際執(zhí)行2。反之亦然。)
? ? method_exchangeImplementations(newAddObject, addObject);
}
- (void)newAddObject:(id)anObject {
? ? @try{
? ? ? ? [selfnewAddObject:anObject];//其實(shí)就是調(diào)用addObject
? ? }
? ? @catch(NSException *exception) {
? ? ? ? //能來到這里,說明可變數(shù)組添加元素的代碼有問題
? ? ? ? //你可以在這里進(jìn)行相應(yīng)的操作處理
? ? ? ? NSLog(@"異常名稱:%@? 異常原因:%@",exception.name, exception.reason);
? ? }
? ? @finally {
? ? ? ? //在這里的代碼一定會執(zhí)行,你也可以進(jìn)行相應(yīng)的操作
? ? }
}
@end
NSException的簡單應(yīng)用
????在項(xiàng)目上傳store后,我們肯定是希望得到程序異常崩潰時的信息,來改進(jìn)自己App。當(dāng)然我們可以集成友盟、百度等產(chǎn)品的bug分析工具。我們自己如何簡單的實(shí)現(xiàn)這一功能呢。
????NSException?可以用來捕獲程序異常crash時的崩潰信息,在捕捉到的時候我們不能直接上傳服務(wù)器 。因?yàn)樯蟼鞯暮臅r操作,可能在程序crash后還尚未完成。我們這時可以將Exception信息保存本地。當(dāng)下次程序打開時,我們來檢測是否存在此文件,如果存在,我們將文件上傳服務(wù)器,成功后,刪除該文件。下面我們來看下代碼實(shí)現(xiàn)。
首先我們需要全局捕獲crash。
void UncaughtExceptionHandler(NSException*exception){
? ? NSArray? *excpArr = [exceptioncallStackSymbols];
? ? NSString*reason = [exceptionreason];
? ? NSString*name = [exceptionname];
? ? NSDictionary* userInfo = [exceptionuserInfo];
? ? NSString *excpCnt = [NSString stringWithFormat:@"exceptionType: %@ \n reason: %@ \n stackSymbols: %@ \n userInfo: %@",name,reason,excpArr,userInfo];
? ? //NSTemporaryDirectory()是沙盒路徑,這里我存在了temp文件下。
? ? NSString * errorMessageFile = [NSString stringWithFormat:@"%@/error.txt",NSTemporaryDirectory()];
? ? //將崩潰信息寫入沙盒里的error.txt文件
? ? [excpCntwriteToFile:errorMessageFile atomically:YES encoding:NSUTF8StringEncoding error:nil];
}
在AppDelegate中- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions方法調(diào)用NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);每次程序打開時,我們運(yùn)行下面代碼:
? ? NSString * errorMessageFile = [NSString stringWithFormat:@"%@/error.txt",NSTemporaryDirectory()];
? ? if ([[NSFileManager defaultManager] fileExistsAtPath:errorMessageFile]) {
? ? //在這里文件進(jìn)行上傳操作
? ? ? ? NSData*data = [NSDatadataWithContentsOfFile:errorMessageFile];
? ? ? ? NSLog(@"%@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
? ? ? ?[ [NetManager Share] putURL:@"******"
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ????file:errorMessageFile?
? ? ????????????????????????????????????????success:^(idresponseData) {
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//上傳成功 , 刪除errorMessageFile
??????? ????????????????????????????????????????????????BOOL blDele= [fileManager removeItemAtPath:errorMessageFile error:nil];
??????? ????????????????????????????????????????????????if (blDele) {
??????????? ????????????????????????????????????????????????????NSLog(@"delete success");
??????? ????????????????????????????????????????????????}else {
??????????? ????????????????????????????????????????????????????NSLog(@"delete fail");
????????????????????????????????????????????????????????}
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }
????????????????????????????????????????????????failure:^(NSString*errorMessage) {
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self.logInViewshowErrorLabelWithMessage:@"* 網(wǎng)絡(luò)連接錯誤,請重試"];
?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ?]
????? };