NSException的使用

异常处理的使用的格式基本就是:


    //如果@try中的代码会导致程序崩溃,就会去到@catch

} @catch(NSException *exception) {

    //如果@try中的代码有问题(导致崩溃),就会来到@catch

    //在这里可以进行相应的处理操作

    //如果你要抛出异常(让程序崩溃),就写上 @throw exception

} @finally {

    //@finally中的代码是一定会执行的

}

觉得需要掌握以下几个方面的内容:

1 要会创建NSException对象,并且会使用@throw抛出异常

2 了解异常处理的作用

使用@try进行异常处理,一开始会有类似下面两个问题弄不明白:

1 既然异常发生了,程序一定会退出,那还需要@final逻辑干嘛,程序退出了一切都重新开始不就行了

2 异常发生后,然后判断是属于哪种异常,使用@catch分别处理的意图是什么呢

举个简单的例子,对数组越界访问:


- (void)testCode {

    NSArray *arr = @[@"abc"];

     NSString *name = [arr objectAtIndex:1];

    NSLog(@">---%@", name);

    if(!name) {

        NSLog(@">---取值失败");

    } else {

        NSLog(@">---取值成功");

    }

}

控制台打印的信息:


2023-02-0317:35:12.956564+0800OCTestLine[22690:1921426] *** Terminating app due to uncaught exception'NSRangeException', reason:'*** __boundsFail: index 3 beyond bounds [0 .. 1]'*** Firstthrow call stack:

(

    0CoreFoundation0x00007fff2dd5ff53__exceptionPreprocess +2501libobjc.A.dylib0x00007fff63e25835objc_exception_throw +482CoreFoundation0x00007fff2de22d3a_CFThrowFormattedException +2023CoreFoundation0x00007fff2de2a203-[__NSArrayI getObjects:range:].cold.1+04CoreFoundation0x00007fff2dcbd061-[__NSSingleObjectSetI member:] +05TestDemo0x0000000100000d97-[TestClass testCode] +1356 +447TestDemo0x0000000100000c47main +878libdyld.dylib0x00007fff651882e5start +1)

libc++abi.dylib: terminating with uncaught exception of type NSException

(lldb)

关于这种越界取值的情况,程序会直接抛出异常,抛出异常的结果就是程序crash(崩溃),这在程序开发过程中相对于“错误”,“异常”导致crash更容易定位bug,这样直截了当地crash的确也没什么,定位bug、修改代码、重新运行就行了,因此在软件开发过程中,“异常处理”的确没什么用。但是如果有以下需求呢?

1 程序闪退之前,我想把这个“异常”信息记录下来,或者记录在本地,或者上传记录在服务器上,方便后期修复优化代码;

2 程序闪退之前,我想把一些“操作”做完,以确保整个系统的安全性;

这样的需求并不过分,比如用户下载了已经发布的版本,使用过程中出现了闪退,肯定是需要进行crash统计的,方便程序员定位问题,腾讯Bugly就是基于此需求开发的框架。

另外,使用异常处理有个现实情况是,当App出现异常闪退了,但是并没有真正的“杀死”进程,这个时候是可以继续使用该App的进程继续做其他操作的(比如上传异常信息到服务器)。


- (void)testCode {

    NSString *name;

    @try {

            NSArray *arr = @[@"abc"];

           name = [arr objectAtIndex:1];

            NSLog(@">---%@", name);

      } @catch(NSException *exception) {

            NSLog(@">---%@", exception);

            for(inti =1; i <10; i++) {

                sleep(1);

                NSLog(@">---将错误信息上传服务器进度:%d%%", i*10);

            }

    } @finally {

        for(inti =10; i >0; i--) {

            sleep(1);

            NSLog(@">---退出程序倒计时:%d", i);

        }

        if(!name) {

            NSLog(@">---通知服务器取值失败");

        } else {

            NSLog(@">---通知服务器取值成功");

        }

    }

}

在控制台的打印结果如下:


2023-02-03 17:28:50.937048+0800 TestDemo[113258:333899] >---*** __boundsFail: index3beyond bounds [0..1]

2023-02-03 17:28:51.938338+0800 TestDemo[113258:333899] >---将错误信息上传服务器进度:10%

2023-02-03 17:28:52.939736+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:20%

2023-02-03 17:28:53.941213+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:30%

2023-02-03 17:28:54.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:40%

2023-02-03 17:28:55.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:50%

2023-02-03 17:28:56.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:60%

2023-02-03 17:28:57.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:70%

2023-02-03 17:28:58.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:80%

2023-02-03 17:28:59.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:90%

2023-02-03 17:29:00.937048+0800 TestDemo[113258:333899]  >---将错误信息上传服务器进度:100%

2023-02-03 17:29:01.937048+0800 TestDemo[113258:333899]  >---退出程序倒计时:10

2023-02-03 17:29:02.937048+0800 TestDemo[113258:333899]  >---退出程序倒计时:9

2023-02-03 17:29:03.958486+0800 TestDemo[113258:333899]  >---退出程序倒计时:8

2023-02-03 17:29:04.958486+0800 TestDemo[113258:333899]  >---退出程序倒计时:7

2023-02-03 17:29:05.963303+0800 TestDemo[113258:333899]  >---退出程序倒计时:6

2023-02-03 17:29:06.963303+0800 TestDemo[113258:333899]  >---退出程序倒计时:5

2023-02-03 17:29:07.965136+0800 TestDemo[113258:333899]  >---退出程序倒计时:4

2023-02-03 17:29:08.967182+0800 TestDemo[113258:333899]  >---退出程序倒计时:3

2023-02-03 17:29:09.969092+0800 TestDemo[113258:333899]  >---退出程序倒计时:2

2023-02-03 17:29:10.970962+0800 TestDemo[113258:333899]  >---退出程序倒计时:1

2023-02-03 17:29:10.971614+0800 TestDemo[113258:333899]  >---通知服务器取值失败

Program ended with exit code: 0

关于控制台打印的信息,有两点说明:

1 仔细看打印的时间,可以知道,异常发生后,app闪退后,后台进程并没有退出,在用户通过“多任务”进行删除app之前,依然可以运行代码做很多事;

2 使用@try正常处理异常,程序是属于正常退出的,“Program ended with exit code:0”

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容