UIAlertView中显示未捕获的NSException

时间:2013-08-22 19:15:47

标签: ios objective-c multithreading grand-central-dispatch

我使用以下方法实现了以下异常处理程序:

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];

    });

注意:我实际上并没有在我的生产代码中抛出异常。这纯粹是为了显示生成未处理异常的位置。

在从已分派回主队列的块中引发异常时,我应该考虑到这一点。

1 个答案:

答案 0 :(得分:1)

NSSetUncaughtExceptionHandler的文档说明您应该在应用程序终止之前进行最后一分钟的错误记录。您不应该期望任何UI在此时工作,并且应该仅在文件系统的某处记录错误的详细信息。当用户再次打开应用程序时,您可以让他们知道出现问题并可能提供恢复/报告选项。

  

讨论
设置顶级错误处理函数,您可以在程序终止之前执行最后一分钟的日志记录。