学会用 try,catch语法捕获异常

对于应用闪退,相信大家见到最多的就是“异常抛出”这个状况,也就是

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中抓到这个异常。


你可能感兴趣的:(ios,exception,异常)