一、概述
iOS-App崩溃分为两种,一种是异常:NSException,一种是信号:Signal。
二、异常崩溃
1.NSException对象
(1)reason:崩溃原因。
(2)callStackSymbols:调用堆栈。
(3)name:崩溃名称
(4)userInfo:崩溃对象。
2.崩溃拦截:
(1)声明异常拦截方法
(2)设置拦截器方法之前,先获取上一个拦截方法
三、信号崩溃
1.设置拦截,并保存上一个设置的拦截方法
2.拦截方法
3.调用上一个设置的拦截方法
iOS-App崩溃分为两种,一种是异常:NSException,一种是信号:Signal。
二、异常崩溃
1.NSException对象
(1)reason:崩溃原因。
(2)callStackSymbols:调用堆栈。
(3)name:崩溃名称
(4)userInfo:崩溃对象。
2.崩溃拦截:
(1)声明异常拦截方法
static void uncaughtExceptionHandler(NSException *exception){}
(2)设置拦截方法
NSSetUncaughtExceptionHandler(&uncaughtExceptionHandler);
3.崩溃拦截衔接
(1)NSSetUncaughtExceptionHandler只维护一个拦截方法,如果在一个App内,有多处设置了拦截方法,则只有最后一个拦截方法生效,所以需要做到拦截衔接。(2)设置拦截器方法之前,先获取上一个拦截方法
NSUncaughtExceptionHandler *lastExceptionHandler = NSGetUncaughtExceptionHandler();
(3)在自己的拦截方法中,调用上一个拦截方法
lastExceptionHandler(exception);
三、信号崩溃
1.设置拦截,并保存上一个设置的拦截方法
//旧的信号处理函数结构体
static struct sigaction oldSigAction_SIGSYS;
static struct sigaction oldSigAction_SIGSEGV;//初始化处理函数结构体
struct sigaction newSigAction;
newSigAction.sa_handler = signalHandler;//在该信号处理函数运行时,内核将不会阻塞该信号、将信号的处理函数重置为缺省值
newSigAction.sa_flags = SA_RESETHAND | SA_NODEFER;//本进程收到SIGQUIT信号,将阻塞该信号,直到signalHandler执行结束才会处理信号SIGQUIT
sigaddset(&newSigAction.sa_mask, SIGQUIT);//添加信号和处理函数的关系,并保存旧的信号处理函数
sigaction(SIGSYS, &newSigAction, &oldSigAction_SIGSYS);
sigaction(SIGSEGV, &newSigAction, &oldSigAction_SIGSEGV);
2.拦截方法
static void signalHandler(int signal)
{//合成堆栈信息void *frames[128];int i, len = backtrace(frames, 128);char **symbols = backtrace_symbols(frames, len);NSMutableString *exceptionContent = [[NSMutableString alloc] initWithCapacity:4096];for (i = 0; i < len; ++i){[exceptionContent appendFormat:@"%s\r\n", symbols[i]];}//释放缓存free(symbols)//调用上一个设置的拦截方法,见3。
}
3.调用上一个设置的拦截方法
switch (signal)
{case SIGSEGV:{if (oldSigAction_SIGSEGV.sa_handler != nil){oldSigAction_SIGSEGV.sa_handler(signal);}break;}case SIGSYS:{if (oldSigAction_SIGSYS.sa_handler != nil){oldSigAction_SIGSYS.sa_handler(signal);}break; }
}