1、手动捕捉crash
即使有了bugly,也需要知道奔溃是如何捕捉的。
注意:自定义NSSetUncaughtExceptionHandler之后,会导致bugly失效,需要注意!!
void UncaughtExceptionHandler(NSException *exception) {
NSArray *arr = [exception callStackSymbols];
NSString *reason = [exception reason];
NSString *name = [exception name];
NSLog(@"\n%@\n%@\n%@",arr,reason,name);
}
int main(int argc, const char * argv[]) {
@autoreleasepool {
//在可能发生奔溃之前就需要完成注册
NSSetUncaughtExceptionHandler(&UncaughtExceptionHandler);
}
- 可以将奔溃收集起来后上传服务器。
2、自定义NSException
//创建异常
NSString *exceptionName = @"hi,我是一个异常";
NSString *excaptionReason = @"我不开心了,所以我要让程序崩溃";
NSDictionary *exceptionUserInfo = nil;
NSException *exception = [NSException exceptionWithName:exceptionName reason:excaptionReason userInfo:exceptionUserInfo];
//抛出异常
@throw exception;
- 当然
NSException
的强大并没有完全展示出来。
3、系统是如何触发自定义奔溃
3.1 在_objc_init
中完成exception初始化
//runtime的初始化函数
void _objc_init(void)
{
...
//crash奔溃的处理
exception_init();
}
void exception_init(void)
{
// _objc_terminate是一个函数指针
old_terminate = std::set_terminate(&_objc_terminate);
}
//系统出现crash都会来到这个函数
static void _objc_terminate(void)
{
if (! __cxa_current_exception_type()) {
// No current exception.
(*old_terminate)();
}
else {
// There is a current exception. Check if it's an objc exception.
@try {
__cxa_rethrow();
} @catch (id e) {
//系统奔溃之后会调用这个uncaught_handler指针函数
(*uncaught_handler)((id)e);
(*old_terminate)();
} @catch (...) {
// It's not an objc object. Continue to C++ terminate.
(*old_terminate)();
}
}
}
- 如果对
_objc_init
何时调用的可以移步OC底层探索16 -应用程序加载
有详细的介绍 - 完成
uncaught_handler
函数指针的设置。
3.2 uncaught_handler
// uncaught_handler 的默认值,什么处理都不做
static void _objc_default_uncaught_exception_handler(id exception)
{}
static objc_uncaught_exception_handler uncaught_handler = _objc_default_uncaught_exception_handler;
-
uncaught_handler
是一个函数指针。
3.3 objc_setUncaughtExceptionHandler
//通过该函数完成uncaught_handler的自定义赋值
objc_uncaught_exception_handler
objc_setUncaughtExceptionHandler(objc_uncaught_exception_handler fn)
{
...
uncaught_handler = fn;
return result;
}
- 将
uncaught_handler
的指针指向了自定义的方法,也就是文章最开始的UncaughtExceptionHandler
函数;等待_objc_terminate
的函数调用。
3.4 NSSetUncaughtExceptionHandler和objc_setUncaughtExceptionHandler关系
函数NSSetUncaughtExceptionHandler
是基于CoreFounation的上层封装,底层是objc_setUncaughtExceptionHandler
这个函数。
- callUncaughtHandler是
NSSetUncaughtExceptionHandler
中完成的赋值,代码就不一一呈现了。