何为异常?
    我的简单理解是:程序可以编译、运行,但是在某些特定的执行环境下会导致程序运行终止,也就是我们常说的崩溃或者闪退现象。

    如何处理?
    我们要抓住这个导致程序运行终止的代码,然后采取合理的方式将其处理掉。Objective-C提供了异常的处理机制

    1. @try {
    2. <#Code that can potentially throw an exception#>
    3. } @catch (NSException *exception) {
    4. <#Handle an exception thrown in the @try block#>
    5. }

    有如下例子:
    1、接下来,我们定义一个Person类

    1. //
    2. // Person.h
    3. // MyObjective-C
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. @interface Person : NSObject
    10. - (void)run;
    11. @end

    在Person类中声明了一个run方法

    2、再看Person类的实现

    1. //
    2. // Person.m
    3. // MyObjective-C
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import "Person.h"
    9. @implementation Person
    10. @end

    在Person类的实现代码中,没有实现run方法

    3、接下来在程序的入口函数中对run方法进行调用

    1. //
    2. // main.m
    3. // ExceptionDeal 异常处理
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. #import "Person.h"
    10. int main(int argc, const char * argv[]) {
    11. Person *person = [Person new];
    12. [person run];
    13. NSLog(@"程序执行到了这里");
    14. return 0;
    15. }

    程序运行到[person run]时,就终止了运行,调试信息显示:run方法声明了,但是没有实现

    1. 2017-10-11 10:03:53.177952+0800 ExceptionDeal[812:23032] -[Person run]: unrecognized selector sent to instance 0x100406730
    2. 2017-10-11 10:03:53.178930+0800 ExceptionDeal[812:23032] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person run]: unrecognized selector sent to instance 0x100406730'
    3. *** First throw call stack:
    4. (
    5. 0 CoreFoundation 0x00007fffb6f012cb __exceptionPreprocess + 171
    6. 1 libobjc.A.dylib 0x00007fffcbd1948d objc_exception_throw + 48
    7. 2 CoreFoundation 0x00007fffb6f82f04 -[NSObject(NSObject) doesNotRecognizeSelector:] + 132
    8. 3 CoreFoundation 0x00007fffb6e73755 ___forwarding___ + 1061
    9. 4 CoreFoundation 0x00007fffb6e732a8 _CF_forwarding_prep_0 + 120
    10. 5 ExceptionDeal 0x0000000100000f26 main + 70
    11. 6 libdyld.dylib 0x00007fffcc5ff235 start + 1
    12. 7 ??? 0x0000000000000001 0x0 + 1
    13. )
    14. libc++abi.dylib: terminating with uncaught exception of type NSException
    15. (lldb)

    4、对这个异常进行处理,使程序可以继续运行

    1. //
    2. // main.m
    3. // ExceptionDeal 异常处理
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. #import "Person.h"
    10. int main(int argc, const char * argv[]) {
    11. Person *person = [Person new];
    12. @try {
    13. //将可能发生异常的代码写在@try块中
    14. [person run];//一旦发生异常,立即执行@catch块中的代码,不会执行@try块中发生异常代码处之后的代码
    15. NSLog(@"我是处于异常后面的代码");
    16. } @catch (NSException *exception) {
    17. //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
    18. NSLog(@"这里是处理异常");
    19. }
    20. NSLog(@"程序执行到了这里");
    21. return 0;
    22. }

    程序运行结果:

    1. 2017-10-11 10:22:36.727478+0800 ExceptionDeal[913:27826] -[Person run]: unrecognized selector sent to instance 0x1002032b0
    2. 2017-10-11 10:22:36.728071+0800 ExceptionDeal[913:27826] 这里是处理异常
    3. 2017-10-11 10:22:36.728109+0800 ExceptionDeal[913:27826] 程序执行到了这里
    4. Program ended with exit code: 0

    5、验证没有异常时不会执行@catch块中的代码,实现Person类中的run方法

    1. //
    2. // Person.m
    3. // MyObjective-C
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import "Person.h"
    9. @implementation Person
    10. - (void)run{
    11. NSLog(@"实现了run方法");
    12. }
    13. @end

    程序运行结果:

    1. 2017-10-11 10:29:33.763648+0800 ExceptionDeal[967:29474] 实现了run方法
    2. 2017-10-11 10:29:33.763909+0800 ExceptionDeal[967:29474] 我是处于异常后面的代码
    3. 2017-10-11 10:29:33.763935+0800 ExceptionDeal[967:29474] 程序执行到了这里
    4. Program ended with exit code: 0

    在@try块中,没有异常时,依次执行了@try块中的所有代码,直接跳过了@catch块

    6、@catch块参数说明

    1. @catch (NSException *exception) {
    2. }

    exception 指针对象,通过它可以拿到发生异常的原因。添加打印异常信息的代码

    1. @catch (NSException *exception) {
    2. //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
    3. NSLog(@"这里是处理异常");
    4. NSLog(@"发生异常的原因:%@", exception);
    5. }

    程序运行结果:

    1. 2017-10-11 10:45:46.946998+0800 ExceptionDeal[1044:33191] -[Person run]: unrecognized selector sent to instance 0x100504590
    2. 2017-10-11 10:45:46.947636+0800 ExceptionDeal[1044:33191] 这里是处理异常
    3. 2017-10-11 10:45:46.947709+0800 ExceptionDeal[1044:33191] 发生异常的原因:-[Person run]: unrecognized selector sent to instance 0x100504590
    4. 2017-10-11 10:45:46.947741+0800 ExceptionDeal[1044:33191] 程序执行到了这里
    5. Program ended with exit code: 0

    7、@finally处理机制说明:位于@try{ }@catch{ }的后面

    1. @try {
    2. <#Code that can potentially throw an exception#>
    3. } @catch (NSException *exception) {
    4. <#Handle an exception thrown in the @try block#>
    5. } @finally {
    6. <#Code that gets executed whether or not an exception is thrown#>
    7. }

    在入口函数中增加@finally块

    1. //
    2. // main.m
    3. // ExceptionDeal 异常处理
    4. //
    5. // Created by ZhaiKun on 2017/10/11.
    6. // Copyright © 2017年 ZhaiKun. All rights reserved.
    7. //
    8. #import <Foundation/Foundation.h>
    9. #import "Person.h"
    10. int main(int argc, const char * argv[]) {
    11. Person *person = [Person new];
    12. @try {
    13. //将可能发生异常的代码写在@try块中
    14. [person run];//一旦发生异常,立即执行@catch块中的代码,不会执行@try块中发生异常代码处之后的代码
    15. NSLog(@"我是处于异常后面的代码");
    16. } @catch (NSException *exception) {
    17. //确定异常已经发生,执行@catch块中的代码。如果@try块中的代码没有发生异常,是不会执行@catch块中的代码的
    18. NSLog(@"这里是处理异常");
    19. NSLog(@"发生异常的原因:%@", exception);
    20. }@finally {
    21. //无论@try块中是否有异常,都会执行这里的代码
    22. NSLog(@"I am finally!");
    23. }
    24. NSLog(@"程序执行到了这里");
    25. return 0;
    26. }

    模拟发生异常时的运行结果:

    1. 2017-10-11 10:57:44.240396+0800 ExceptionDeal[1141:36516] -[Person run]: unrecognized selector sent to instance 0x100202330
    2. 2017-10-11 10:57:44.241212+0800 ExceptionDeal[1141:36516] 这里是处理异常
    3. 2017-10-11 10:57:44.241259+0800 ExceptionDeal[1141:36516] 发生异常的原因:-[Person run]: unrecognized selector sent to instance 0x100202330
    4. 2017-10-11 10:57:44.241286+0800 ExceptionDeal[1141:36516] I am finally
    5. 2017-10-11 10:57:44.241301+0800 ExceptionDeal[1141:36516] 程序执行到了这里
    6. Program ended with exit code: 0

    模拟没有异常出现时的运行结果:

    1. 2017-10-11 10:58:37.252254+0800 ExceptionDeal[1177:36918] 实现了run方法
    2. 2017-10-11 10:58:37.252422+0800 ExceptionDeal[1177:36918] 我是处于异常后面的代码
    3. 2017-10-11 10:58:37.252447+0800 ExceptionDeal[1177:36918] I am finally
    4. 2017-10-11 10:58:37.252465+0800 ExceptionDeal[1177:36918] 程序执行到了这里
    5. Program ended with exit code: 0

    得出结论:无论在@try块中是否有异常,程序最终都会执行@finally块中的代码

    注意:@try、、、@catch对异常的处理是有一定的局限性的,也就是说这个东东是不能处理所有的异常的,典型的例子就是做除法运算时分母为0的情况。那么我们又怎么样对它不能处理的异常进行处理呢?推荐的方法是:进行逻辑判断处理。