在开发 iOS
应用,解决 Crash
问题始终是一个难题。Crash
分为两种,一种是由 EXC_BAD_ACCESS
引起的,原因是访问了不属于本进程的内存地址,有可能是访问已被释放的内存;另一种是未被捕获的 Objective-C
异常,导致程序向自身发送了 UNIX
信号而崩溃。对于这两种 Crash
的捕获,精准高效的收集线上崩溃可以帮助我们更好的解决问题和提高用户体验,现在比较成熟的崩溃收集工具也比较多,比如:友盟统计,Crashlytics
,腾讯的 bugly
等等。也可以通过自定义 crash
上报,来处理异常。
但是当自定义 crash
上报收集工具与第三方 crash
收集工具共存的时候,发现自定义 crash
上报收集工具,不能捕获到 exception
。
/* Set the uncaught exception handler */
NSSetUncaughtExceptionHandler(&uncaught_exception_handler);
不管是第三方还是自定义的上报收集工具,一般会常用注册 ExceptionHandler
的方式,来捕获 exception
,但是并没有将异常进行抛出,所以,当工程中使用了第三方上报收集工具进行异常统计的时候,我们自己写的异常捕获有可能会失效。
首先保存第三方的 ExceptionHandler
,然后在设置自己处理 exception
的 ExceptionHandler
,在自己的 ExceptionHandler
处理完异常之后,再将异常塞给之前的第三方 ExceptionHandler
。
static NSUncaughtExceptionHandler *_previousHandler;
// 保存第三方处理异常的 handler
_previousHandler = NSGetUncaughtExceptionHandler();
// 设置自己处理异常的 handler
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandlerYourself);
处理自己的异常
void UncaughtExceptionHandlerYourself (NSException *exception) {
}
处理完自己的逻辑之后就需要把 exception
赋值给我们之前保存的handler
,否则第三方就无法统计到崩溃的数据。
_previousHandler(exception);
总结,通过这种方法,第三方和我们上报收集工具,都可以正常的收集崩溃数据。第三方上报收集工具捕获到异常,再处理完自己的逻辑后,将 exception
抛了出来,我们自己的崩溃日志收集库收到第三方上报收集工具抛出来的 exception
,处理完自己的逻辑后再将 exception
抛给第三方上报收集工具的 handler
。