0

我已经使用以下异常处理程序实现了:

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

    });

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

当从已分派回主队列的块中引发异常时,应该考虑我遗漏了什么。

4

1 回答 1

1

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

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

于 2013-08-22T20:25:27.187 回答