我已经使用以下异常处理程序实现了:
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];
});
注意:我实际上并没有在我的生产代码中抛出异常。这纯粹是为了显示未处理的异常是在哪里生成的。
当从已分派回主队列的块中引发异常时,应该考虑我遗漏了什么。