主要捕获两种崩溃类型:NSException和Signal异常。
NSException是什么?
NSException是一个中断程序正常执行的描述对象,包含异常名称、通俗的原因描述、以及包含补充消息的字典。
@interface NSException : NSObject <NSCopying, NSCoding> {
@private
NSString *name;//名称
NSString *reason;//原因
NSDictionary *userInfo;//补充信息
id reserved;
}
其中name的值是NSExceptionName类型的字符串。常见值:
-
NSInvalidArgumentException:插入nil到容器类
-
NSRangeException:容器类越界或者字符串越界
-
更多请参考苹果开发者文档
-
developer.apple.com/documentati…
对于排查问题来说,名称其实不重要,重要的是通俗易懂的reason描述以及堆栈信息。
如何捕获NSException异常
关键方法:
//执行NSException的方法,将自定义的异常处理的函数地址传进去,发生异常时,会调用该函数。
NSSetUncaughtExceptionHandler(NSUncaughtExceptionHandler * _Nullable);
Doraemon完整代码
// DoraemonCrashUncaughtExceptionHandler.m
#import "DoraemonCrashUncaughtExceptionHandler.h"
#import "DoraemonCrashTool.h"
// 记录之前的崩溃回调函数
static NSUncaughtExceptionHandler *previousUncaughtExceptionHandler = NULL;
@implementation DoraemonCrashUncaughtExceptionHandler
#pragma mark - Register
+ (void)registerHandler {
// 备份现有的异常处理,在自己的处理函数中调用,防止多处设置异常函数时,后者替换前者,导致前者捕获不到异常的情况
previousUncaughtExceptionHandler = NSGetUncaughtExceptionHandler();
// 设置自定义的异常处理函数
NSSetUncaughtExceptionHandler(&DoraemonUncaughtExceptionHandler);
}
#pragma mark - Private
// 崩溃时的回调函数
static void DoraemonUncaughtExceptionHandler(NSException * exception) {
// 异常的堆栈信息
NSArray * stackArray = [exception callStackSymbols];
// 出现异常的原因
NSString * reason = [exception reason];
// 异常名称
NSString * name = [exception name];
NSString * exceptionInfo = [NSString stringWithFormat:@"========uncaughtException异常错误报告========\nname:%@\nreason:\n%@\ncallStackSymbols:\n%@", name, reason, [stackArray componentsJoinedByString:@"\n"]];
// 保存崩溃日志到沙盒cache目录
[DoraemonCrashTool saveCrashLog:exceptionInfo fileName:@"Crash(Uncaught)"];
// 调用之前崩溃的回调函数