NSError和NSException的几点说明

时间:2022-02-08 05:30:26

有关NSError和NSException基本用法的文章烂到满大街,本篇博文旨在避开常规方式,从几个要点理解NSError和NSException类。


1. 使用属性/方法来访问本地化字符串信息而不是通过userInfo字典

先来看两个例子,然后解释原因

第一个例子:

NSError和NSException的几点说明

输出结果如下:

NSError和NSException的几点说明


第二个例子:

在继承自NSError的自定义类JXError中覆写localizedDescription方法

NSError和NSException的几点说明

然后按照例一方式输出结果如下:

NSError和NSException的几点说明


现在解释原因,例一虽然没有传入本地化的描述信息,但依然可以通过localizedDescription属性获取到,这是因为当userInfo字典没有包含描述信息时,localizedDescription方法就会使用域和错误编码构造错误描述信息,或者从对应域的函数或方法中获取适当的字符串构造错误描述信信息;例二通过覆写方法从新定义了描述信息的格式,然而这些信息并没有存储到userInfo字典里,所以我们依然无法通过userInfo字典获取到错误信息。



2. 未捕获的异常

当某些异常没有被捕获时,会调用UncaughtExceptionHandler函数,通常UncaughtExceptionHandler函数会使程序退出,在这之前我们可以做一些收集异常的任务,通过NSSetUncaughtExceptionHandler可以自定义函数处理未被捕获的异常。

示例如下:

NSError和NSException的几点说明

每次启动app的时候可以把异常信息上传到指定的地址,方便及时处理异常错误。

然而,以上方法能处理的异常比较有限,诸如数组越界、无效参数等,对野指针、内存溢出等问题却束手无策,下面介绍一种通过信号回调的方式收集异常的方法。

这种方法的原理是当产生野指针、内存溢出等异常时,系统会向应用发送一个信号以中断应用正常的控制流程,如果应用定义了信号的处理函数,就会去执行这个函数,收集异常信息的任务就可以放在这个函数中。

示例代码如下:

NSError和NSException的几点说明

以上两种方法可以结合使用,虽然第二种方法没有给出抛出异常的具体代码,但是可以确定异常的类型,也就给出了定位的方向。

进一步缩小野指针异常范围以及重现异常可参考点击打开链接



3. NSError为主,NSException为辅

Apple提供了错误处理和异常处理两种机制,这两种机制的适用范围和职能并不相同。错误处理是一种运行时的处理机制,处理诸如文件读取错误、网络下载失败等运行时问题,这些问题在程序运行中随时都可能出现,而且是可以恢复的,开发者要做的是根据需求为用户提供尽可能详细的错误信息和友好的解决策略。异常处理是解决编程错误的处理机制,处理诸如数组越界、无效参数等错误,理想情况下,异常需要在产品发布之前全部解决,事实却是发布的产品也依然会存在一些问题,比如内存溢出、无效内存访问等,异常处理机制的职能正是帮助开发者尽快定位出异常所在。

此外,由于Cocoa中的框架不是异常安全的,容易造成内存管理的问题,虽然在arc下可以使用-fobjc-arc-exceptions编译选项安全处理异常,但是会生成管理对象生命周期的相关代码,导致应用程序变大,降低运行效率,因此,只应使用异常检测无法恢复的编程错误和意外的运行时错误,并在检测到异常后立刻终止程序。