runtime+NSException來規(guī)避項(xiàng)目開發(fā)中的常見型問題

????????在我們項(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ò)連接錯誤,請重試"];

?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? } ?]

????? };

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

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

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