虽然大家都不愿意看到程序崩溃,但可能崩溃是每个应用必须面对的现实,既然崩溃已经发生,无法阻挡了,那我们就让它崩也崩得淡定点吧。
IOS SDK中提供了一个现成的函数 NSSetUncaughtExceptionHandler 用来做异常处理,但功能非常有限,而引起崩溃的大多数原因如:内存访问错误,重复释放等错误就无能为力了,因为这种错误它抛出的是Signal,所以必须要专门做Signal处理。
在didFinishLaunchingWithOptions 中,加入
代码如下:
Source code
- signal(SIGABRT, MySignalHandler);
- signal(SIGILL, MySignalHandler);
- signal(SIGSEGV, MySignalHandler);
- signal(SIGFPE, MySignalHandler);
- signal(SIGBUS, MySignalHandler);
- signal(SIGPIPE, MySignalHandler);
回调函数MySignalHandler的定义如下:
- void MySignalHandler(int signal)
- {
- int32_t exceptionCount = OSAtomicIncrement32(&UncaughtExceptionCount);
- if (exceptionCount > UncaughtExceptionMaximum)
- {
- return;
- }
- NSMutableDictionary *userInfo =[NSMutableDictionary dictionaryWithObject:[NSNumber numberWithInt:signal]
- forKey:UncaughtExceptionHandlerSignalKey];
- NSArray *callStack = [UncaughtExceptionHandler backtrace];
- [userInfo setObject:callStack forKey:UncaughtExceptionHandlerAddressesKey];
- [[[[UncaughtExceptionHandler alloc] init] autorelease]
- performSelectorOnMainThread:@selector(handleException:)
- withObject:
- [NSException
- exceptionWithName:UncaughtExceptionHandlerSignalExceptionName
- reason:
- [NSString stringWithFormat:
- NSLocalizedString(@"Signal %d was raised.\n"
- @"%@", nil),
- signal, getAppInfo()]
- userInfo:
- [NSDictionary dictionaryWithObject:[NSNumber numberWithInt:signal] forKey:UncaughtExceptionHandlerSignalKey]] waitUntilDone:YES];
- }
- 这段代码将会在崩溃时弹出一个对话框,我们还可以让它显示出设备信息,如下:
- NSString* getAppInfo()
- {
- NSString *appInfo = [NSString stringWithFormat:@"App : %@ %@(%@)\nDevice : %@\nOS Version : %@ %@\nUDID : %@\n",
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"],
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"],
- [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"],
- [UIDevice currentDevice].model,
- [UIDevice currentDevice].systemName,
- [UIDevice currentDevice].systemVersion,
- [UIDevice currentDevice].uniqueIdentifier];
- NSLog(@"Crash!!!! %@", appInfo);
- return appInfo;
- }
这样在崩溃时还能从容地弹出对话框,比起闪退来,用户也不会觉得那么不爽。然后在下次启动时还可以通过邮件来发送Crash文件到邮箱,这就看各个应用的需求了。
原文来自:触控科技博客