學會用 try,catch語法捕獲異常
阿新 • • 發佈:2019-02-06
對於應用閃退,相信大家見到最多的就是“異常丟擲”這個狀況,也就是
NSException這個么蛾子搞的鬼。那麼今天就來面對它。也就是利用@try 語法來捕獲它。並且做出相應的善後工作。不讓程式閃退。
模擬一個異常 : array 是不可變陣列,然後我們在函式dosomething 中給他addobject
-(void)dosomething:(NSMutableArray*)input
{
[input addObject:@"test"];
}
<pre name="code" class="objc"> NSArray* array = [NSArray new];
[self dosomething:array];
然後我們執行,結果可想而知,程式閃退,並且輸出如下資訊:
異常原因可以看到,程式也如願閃退。2014-10-29 16:51:35.567 warning[3901:133943] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x786385f0 2014-10-29 16:51:35.571 warning[3901:133943] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI addObject:]: unrecognized selector sent to instance 0x786385f0' *** First throw call stack: ( 0 CoreFoundation 0x008b0df6 __exceptionPreprocess + 182 1 libobjc.A.dylib 0x0053aa97 objc_exception_throw + 44 2 CoreFoundation 0x008b8a75 -[NSObject(NSObject) doesNotRecognizeSelector:] + 277 3 CoreFoundation 0x008019c7 ___forwarding___ + 1047 4 CoreFoundation 0x0080158e _CF_forwarding_prep_0 + 14 5 warning 0x0005c857 -[AppDelegate dosomething:] + 103 6 warning 0x0005c791 -[AppDelegate application:didFinishLaunchingWithOptions:] + 161 7 UIKit 0x00c5bedc -[UIApplication _handleDelegateCallbacksWithOptions:isSuspended:restoreState:] + 291 8 UIKit 0x00c5cbe7 -[UIApplication _callInitializationDelegatesForMainScene:transitionContext:] + 2869 9 UIKit 0x00c6016d -[UIApplication _runWithMainScene:transitionContext:completion:] + 1639 10 UIKit 0x00c78d30 __84-[UIApplication _handleApplicationActivationWithScene:transitionContext:completion:]_block_invoke + 59 11 UIKit 0x00c5ed7f -[UIApplication workspaceDidEndTransaction:] + 155 12 FrontBoardServices 0x031d79de __37-[FBSWorkspace clientEndTransaction:]_block_invoke_2 + 71 13 FrontBoardServices 0x031d746f __40-[FBSWorkspace _performDelegateCallOut:]_block_invoke + 54 14 FrontBoardServices 0x031e9425 __31-[FBSSerialQueue performAsync:]_block_invoke + 26 15 CoreFoundation 0x007d47a0 __CFRUNLOOP_IS_CALLING_OUT_TO_A_BLOCK__ + 16 16 CoreFoundation 0x007ca0b3 __CFRunLoopDoBlocks + 195 17 CoreFoundation 0x007c9f0b __CFRunLoopRun + 2715 18 CoreFoundation 0x007c91ab CFRunLoopRunSpecific + 443 19 CoreFoundation 0x007c8fdb CFRunLoopRunInMode + 123 20 UIKit 0x00c5e744 -[UIApplication _run] + 571 21 UIKit 0x00c61e16 UIApplicationMain + 1526 22 warning 0x0005ccfd main + 141 23 libdyld.dylib 0x02bfeac9 start + 1 ) libc++abi.dylib: terminating with uncaught exception of type NSException
我們對上面的程式碼做一些修改。
NSArray* array = [NSArray new];
@try {
[self dosomething:array];
}
@catch (NSException *exception) {
NSLog(@"-----%@",exception.description);
}
@finally {
NSLog(@"over");
}
重新跑一遍。輸出log如下應用程式也沒有閃退。2014-10-29 16:55:31.308 warning[3942:136578] -[__NSArrayI addObject:]: unrecognized selector sent to instance 0x7be13470 2014-10-29 16:55:31.309 warning[3942:136578] ------[__NSArrayI addObject:]: unrecognized selector sent to instance 0x7be13470 2014-10-29 16:55:31.309 warning[3942:136578] over
我來解釋一下這段程式碼以及log輸出。
使用try 語法呼叫那些可能導致異常的程式碼段。這裡就一個函式呼叫。
如果有異常丟擲,異常被catch捕獲,並且你可以知道異常資訊。也就是exception。
最後finally無論有沒有異常都會走。
log 第一行是應用自身丟擲的異常log,可見在應用丟擲異常之後,馬上被我們的catch 捕獲到,並且按照我們的要求輸出了異常資訊。
最後進入finally裡面。
當然這個語法是可以巢狀。確保異常一定會得到處理。
可以在函式 dosomething 裡面加上try 語法
-(void)dosomething:(NSMutableArray*)input
{
@try {
[input addObject:@"test"];
}
@catch (NSException *exception) {
NSLog(@"======= %@",exception.description);//如果這裡不能處理異常,需要向外層繼續丟擲 @throw;
}
@finally {
NSLog(@"finally");
}
}
這樣在函式內部,也會有一個捕獲異常的過程。值得一說的是,如果你在函式內部不能處理,需要丟擲去讓外層處理。
這樣外層依然能在@catch中抓到這個異常。