iOS:后台线程异常不会崩溃

7

我没有找到与我的经验一致的文档。

我想要一个处理后台线程中未捕获异常的好方法。这个“方法”应该让应用程序崩溃,但在崩溃之前执行一些非常基本的操作(例如将值保存到UserDefaults中,以便在下次启动时检查;还有记录日志)。

在主线程上,我只需设置一个uncaughtExceptionHanlder,这很好用。然而,在作为NSOperationQueue上的NSOperation执行的后台线程上,任何异常都会发生 但不会退出应用程序:崩溃。应用程序继续在已损坏的状态下运行。

但是,线程编程指南指出:

设置异常处理程序 如果应用程序捕获和处理异常,则线程代码应准备捕获可能发生的任何异常。尽管最好在可能发生异常的地方处理异常,但在线程中无法捕获抛出的异常会导致应用程序退出。 在您的线程入口例程中安装最终的try / catch允许您捕获任何未知异常并提供适当的响应。

一个可行的方法(见下文)是使用try/catch嵌入线程调用方法,并在出现异常的情况下记录日志,然后调用abort()。但这不能是最好的方法。我想将异常发送到主线程,并由未捕获异常处理程序处理。 有人做过吗?

- (void)threadMethod
{
    @try
    {
        NSArray* aTest = [NSArray array];
        [aTest objectAtIndex:10];
    }
    @catch (NSException* e)
    {
        // Save to state to User Defaults.
        // Log any needed info.

        abort();
    }
    @finally
    {

    }
}

提醒一下:我正在使用iOS6和XCode 4.5 SDK。

2个回答

6
  1. NSOperationQueue管理的线程由libdispatch管理,它会捕获异常并调用terminate退出应用程序。如果您看到不同的行为,那么您已经做错了什么。
  2. 在异常发生后将数据保存到NSUserDefaults可能会有问题;因为Cocoa只将异常视为程序员错误,所以一旦抛出异常,它就不会尝试保持自己处于可用状态。简而言之,您应该像处理“真正”的崩溃一样对待它,好像只有异步信号安全的API是可用的。在这方面,任何Objective-C都自动排除。
  3. 您的问题表明您正在尝试进行崩溃报告。我建议使用崩溃报告解决方案,例如PLCrashReporter。还有一些分析和分发服务嵌入了崩溃报告,包括HockeyAppCrashlyticsTestFlightQuincyKit。还有其他的选择,哪一个适合您取决于您的需求。所有这些服务都将处理处理崩溃和异常的所有棘手问题,并安全地保存数据以供以后使用,而您无需担心任何问题。

这不是崩溃报告的问题。在发生崩溃的情况下,我想要存储用于下一次启动的状态信息。 - paiego
我的第一反应是你最好将数据以尽可能简单的格式写入文件中,使用普通的POSIX API。再次强调,当异常即将导致应用程序崩溃时,Objective-C 中的任何东西都是不安全的;所有内容都处于未知状态。一个非常快速的示例可能是:int fd = open(UTF8StringOfDocumentsDirectoryPlusFileNameSavedAtAppStartup, O_WRONLY | O_CREAT | O_TRUNC); if (fd != -1) { write(fd, "crashed", sizeof("crashed") - 1); close(fd); } - Gwynne Raskind

0
我认为,针对你正在做的事情,你需要在主线程中编写代码来检查第二个线程中发生的事情。由于你无法实际联系主线程并从后台线程触发事件,因此你很可能会被困在主线程中不断检查的情况下。话虽如此,你可以尝试使用NSNotificationCenter,在后台线程抛出异常时,让主线程触发一个事件。祝好运。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接