我使用以下方法实现了以下异常处理程序:
NSSetUncaughtExceptionHandler(&ExceptionHandler)
然后,处理程序使用以下命令调用handleException:
[[AppContext alloc] init] performSelectorOnMainThread:@selector(handleException:) withObject:exception waitUntilDone:YES];
这是如此实施的:
NSString *message = [NSString stringWithFormat:MSG_UNHANDLED_EXCEPTION_FORMAT, exception.reason, [exception callStackSymbols]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:TITLE_UNHANDLED_EXCEPTION message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
[alert show];
CFRunLoopRef runLoop = CFRunLoopGetCurrent();
CFArrayRef allModes = CFRunLoopCopyAllModes(runLoop);
while (!_quit) {
for (NSString *mode in (__bridge NSArray *)allModes) {
CFRunLoopRunInMode((__bridge CFStringRef)mode, 0.001, false);
}
}
CFRelease(allModes);
除以下场景外,此方法效果很好。我仍然可以显示UIAlertView,但用户交互不再可用(用户无法滚动消息或点击确定)。
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(){
// do long work on another thread...
dispatch_async(dispatch_get_main_queue(), ^(){
// updating the UI so get back on main thread...
// exception occurs in this block (example)...
@throw [NSException exceptionWithName:@"DispatchAsyncToMainThreadException" reason:@"Example" userInfo:nil];
});
注意:我实际上并没有在我的生产代码中抛出异常。这纯粹是为了显示生成未处理异常的位置。
在从已分派回主队列的块中引发异常时,我应该考虑到这一点。
答案 0 :(得分:1)
NSSetUncaughtExceptionHandler
的文档说明您应该在应用程序终止之前进行最后一分钟的错误记录。您不应该期望任何UI在此时工作,并且应该仅在文件系统的某处记录错误的详细信息。当用户再次打开应用程序时,您可以让他们知道出现问题并可能提供恢复/报告选项。
讨论
设置顶级错误处理函数,您可以在程序终止之前执行最后一分钟的日志记录。