強(qiáng)大的NSException

一、NSException簡(jiǎn)介

1.什么是NSException?

說到NSException你可能不太了解,但是下面的這張圖你肯定見過不止一次


exception

這些就是NSException產(chǎn)生的,一旦程序拋出異常,程序就會(huì)崩潰,控制臺(tái)就會(huì)有這些崩潰日志。

2、定義一個(gè)NSException對(duì)象并拋出

NSString*name =@"exception name";

NSString*reason =@"exception reason";

NSException*exception = [NSException exceptionWithName:name reason:reason userInfo:nil];

@throw exception;

運(yùn)行程序會(huì)發(fā)現(xiàn)輸出和上圖類似的日志:

exception

二、異常的簡(jiǎn)單處理

如果你在開發(fā)過程中可能對(duì)某段代碼不信任,也就是有崩潰的可能,而在線上直接報(bào)錯(cuò)又會(huì)影響又會(huì)體驗(yàn),那你就可以通過如下的方法處理:

NSMutableArray*array = [NSMutableArray array];

NSString*nilStr =nil;

@try{

//有可能會(huì)出現(xiàn)異常的代碼,這里寫的代碼一定會(huì)出現(xiàn)問題

[array insertObject:nilStr atIndex:0];

}@catch(NSException *exception) {

//如果@try中的代碼出現(xiàn)異常,就會(huì)執(zhí)行這里的代碼,也就可以在這里進(jìn)行相應(yīng)操作

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

//如果想要拋出異常就執(zhí)行如下代碼,程序就會(huì)崩潰,便于調(diào)試

// @throw exception;

}@finally{

//這里的代碼一定會(huì)執(zhí)行

}

三、防止?jié)撛诘谋罎L(fēng)險(xiǎn)

如果你并不知道程序運(yùn)行到哪里會(huì)出現(xiàn)異常,或者說對(duì)于Foundation框架里有非常多常用的方法有導(dǎo)致崩潰的潛在危險(xiǎn),那么該如何攔截潛在的異常風(fēng)險(xiǎn),并進(jìn)行相應(yīng)的處理,防止崩潰的出現(xiàn)呢?

解決辦法是:

1.利用iOS的runtime特性和catalog添加新方法,替換掉系統(tǒng)的存在異常風(fēng)險(xiǎn)的方法。

2.利用異常捕獲防止程序崩潰,并進(jìn)行相應(yīng)處理。

具體的步驟:

1.創(chuàng)建一個(gè)HandleCrash類:

TXHandleCrash.h

#import

#define HandleCrashLogBegin @"==========================handleCrashLogBegin==========================="

#define HandleCrashLogEnd @"=============================handleCrash==============================="

#define HandleCrashLogNotification @"HandleCrashLogNotification"

@interfaceTXHandleCrash :NSObject

/**

start handle crash

*/

+(void)startHandle;

/**

exchange class method

*/

+(void)handleClass:(Class)anClass exchangeClassMethod:(SEL)method1 Method:(SEL)method2;

/**

exchange instance method

*/

+(void)handleClass:(Class)anClass exchangeCInstanceMethod:(SEL)method1 Method:(SEL)method2;

/**

handle exception

@param remark remark

*/

+(void)handleException:(NSException*)exception remark:(NSString*)remark;

@end

TXHandleCrash.m

#import"TXHandleCrash.h"

#import

#import"NSDictionary+TXHandleCrash.h"

@implementationTXHandleCrash

+(void)startHandle

{

dispatch_once_ttoken;

dispatch_once(&token , ^{

[NSDictionaryhandleCrash];

});

}

+(void)handleClass:(Class)anClass exchangeClassMethod:(SEL)method1 Method:(SEL)method2

{

Methodmtd1 =class_getClassMethod(anClass, method1);

Methodmtd2 =class_getClassMethod(anClass, method2);

method_exchangeImplementations(mtd1, mtd2);

}

+(void)handleClass:(Class)anClass exchangeCInstanceMethod:(SEL)method1 Method:(SEL)method2

{

Methodmtd1 =class_getInstanceMethod(anClass, method1);

Methodmtd2 =class_getInstanceMethod(anClass, method2);

method_exchangeImplementations(mtd1, mtd2);

}

+(void)handleException:(NSException*)exception remark:(NSString*)remark

{

//堆棧數(shù)據(jù)

NSArray*callStackSymbols = [NSThreadcallStackSymbols];

//獲取在哪個(gè)類的哪個(gè)方法中實(shí)例化的數(shù)組,并格式化:-[類名方法名]、+[類名方法名]

NSString*locationMsg = [selflocationExcptionThroughCallStackSymbols:callStackSymbols];

if(!locationMsg) {

locationMsg =@"崩潰位置定位失敗,請(qǐng)查看函數(shù)調(diào)用棧排查錯(cuò)誤";

}

NSString*exceptionName = exception.name;

NSString*exceptionReason = exception.reason;

NSString*exceptionLocation = [NSStringstringWithFormat:@"exception location:%@",locationMsg];

NSString*exceptionMsg = [NSStringstringWithFormat:@"\n\n%@\n\n%@\n%@\n%@\n%@\n\n%@\n\n",HandleCrashLogBegin, exceptionName, exceptionReason, exceptionLocation, remark,HandleCrashLogEnd];

NSLog(@"%@", exceptionMsg);

NSDictionary*exceptionInfoDic =@{

@"exceptionName": exceptionName,

@"exceptionReason": exceptionReason,

@"exceptionLocation": exceptionLocation,

@"remark": remark,

@"exception": exception,

@"callStackSymbols": callStackSymbols

};

//將錯(cuò)誤信息放在字典里,用通知的形式發(fā)送出去

[[NSNotificationCenterdefaultCenter]postNotificationName:HandleCrashLogNotificationobject:niluserInfo:exceptionInfoDic];

}

+(NSString*)locationExcptionThroughCallStackSymbols:(NSArray*)callStackSymbols

{

__blockNSString*locationMsg =nil;

NSLog(@"callStackSymbols=%@",callStackSymbols);

//通過正則匹配出的格式為,-[類名方法名]、+[類名方法名]

NSString*regularExpStr =@"[-\\+]\\[.+\\]";

NSRegularExpression*regularExp = [[NSRegularExpressionalloc]initWithPattern:regularExpStroptions:NSRegularExpressionCaseInsensitiveerror:nil];

for(intindex =2; index

NSString*callStackSymbol = callStackSymbols[index];

[regularExpenumerateMatchesInString:callStackSymboloptions:NSMatchingReportProgressrange:NSMakeRange(0, callStackSymbol.length)usingBlock:^(NSTextCheckingResult*_Nullableresult,NSMatchingFlagsflags,BOOL*_Nonnullstop) {

if(result) {

NSString*tmpLocationMsg = [callStackSymbolsubstringWithRange:result.range];

//get class name

NSString*className = [tmpLocationMsgcomponentsSeparatedByString:@" "].firstObject;

className = [classNamecomponentsSeparatedByString:@"["].lastObject;

NSBundle*bundle = [NSBundlebundleForClass:NSClassFromString(className)];

//filter catalog and system Class

if(![classNamehasPrefix:@")"] && bundle == [NSBundlemainBundle]) {

locationMsg = tmpLocationMsg ;

}

*stop =YES;

}

}];

if(locationMsg.length) {

break;

}

}

returnlocationMsg ;

}

@end

2.創(chuàng)建一個(gè)NSDictionary的catalog

NSDictionary+TXHandleCrash.h

#import

@interfaceNSDictionary (TXHandleCrash)

+(void)handleCrash;

@end

NSDictionary+TXHandleCrash.m

#import"NSDictionary+TXHandleCrash.h"

#import"TXHandleCrash.h"

@implementationNSDictionary (TXHandleCrash)

+(void)handleCrash

{

[TXHandleCrashhandleClass:[selfclass]exchangeClassMethod:@selector(dictionaryWithObjects:forKeys:count:)Method:@selector(handleCrashDictionaryWithObjects:forKeys:count:)];

}

+(instancetype)handleCrashDictionaryWithObjects:(constid_Nonnull__unsafe_unretained*)objects forKeys:(constid_Nonnull__unsafe_unretained*)keys count:(NSUInteger)cnt

{

idinstance =nil;

@try{

instance = [selfhandleCrashDictionaryWithObjects:objectsforKeys:keyscount:cnt];

}@catch(NSException *exception) {

[TXHandleCrashhandleException:exceptionremark:@""];

NSUIntegerindex =0;

id_Nonnull__unsafe_unretainednewObjects[cnt];

id_Nonnull__unsafe_unretainednewKeys[cnt];

for(inti =0; i

if(keys[i] && objects[i]) {

newObjects[index] = objects[i];

newKeys[index] = keys[i];

index ++ ;

}

}

instance = [selfhandleCrashDictionaryWithObjects:newObjectsforKeys:newKeyscount:index];

}@finally{

returninstance ;

}

}

@end

3.在Appdelegate中

- (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {

[TXHandleCrashstartHandle];

[[NSNotificationCenterdefaultCenter]addObserver:selfselector:@selector(handleException:)name:HandleCrashLogNotificationobject:nil];

returnYES;

}

-(void)handleException:(NSNotification*)notif

{

NSDictionary*exceptionInfo = notif.userInfo;

NSLog(@"----------%@",exceptionInfo);

}

4.在viewcontroller中

- (void)viewDidLoad {

[superviewDidLoad];

NSString*nilStr =nil;

//通過這種方法創(chuàng)建字典其實(shí)是調(diào)用dictionaryWithObjects:forKeys:count:方法,如果不做任何處理下面的代碼就會(huì)直接崩潰,現(xiàn)在經(jīng)常上面那么多的處理就不會(huì)崩潰了,并且可以通過AppDelegate中的通知做到收集崩潰日志的目的

NSDictionary*dictionary =@{@"key1":nilStr,@"key2":@"values"};

NSLog(@"dic=%@",dictionary);

}

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

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

  • 轉(zhuǎn)至元數(shù)據(jù)結(jié)尾創(chuàng)建: 董瀟偉,最新修改于: 十二月 23, 2016 轉(zhuǎn)至元數(shù)據(jù)起始第一章:isa和Class一....
    40c0490e5268閱讀 2,069評(píng)論 0 9
  • 我們常常會(huì)聽說 Objective-C 是一門動(dòng)態(tài)語言,那么這個(gè)「動(dòng)態(tài)」表現(xiàn)在哪呢?我想最主要的表現(xiàn)就是 Obje...
    Ethan_Struggle閱讀 2,345評(píng)論 0 7
  • 本篇文章在《iOS開發(fā)之Runtime常用示例總結(jié)》基礎(chǔ)上修改,地址是「:」http://www.cocoachi...
    小__小閱讀 1,934評(píng)論 1 3
  • 這幾天二寶睡得不太好,白天我沒有陪他睡,在看書復(fù)習(xí),中午飯點(diǎn)時(shí)也會(huì)偷懶看下電視,是爸的平板放的熱播劇。 8點(diǎn)左右,...
    小丫屠閱讀 273評(píng)論 0 1
  • 杭州是一座令人流連忘返的城市,她的美在于山、水、人情及整個(gè)城市的溫柔,欣賞完美麗的景色,別忘了在雙腳微酸的時(shí)候,找...
    余元明閱讀 1,565評(píng)論 0 0

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