iOS - 在main()中捕获异常

GRW*_*GRW 2 exception-handling ios

所以,我有一个想法,在main中捕获意外的异常并尝试清理并优雅地退出:

int main(int argc, char *argv[])
{
    @autoreleasepool
    {
        //return UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
        @try
        {
            int retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
            return retVal;
        }
        @catch (NSException *exception)
        {
            [Utilities setPreferencesDefaults];
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这会捕获异常并更新首选项默认值.

然后我想,为什么退出,只是清理和重新启动,所以我把所有东西都包裹在while循环中:

int main(int argc, char *argv[])
{
    while (YES)
    {
        @autoreleasepool
        {
            ...
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

当然,如果真的有效,我就不会在这里.问题是,一旦它再次执行

retVal = UIApplicationMain(argc, argv, nil, NSStringFromClass([GRWAppDelegate class]));
Run Code Online (Sandbox Code Playgroud)

它会立即抛出一个新的异常:

Assertion failure in void UIApplicationInstantiateSingleton(Class)(), /SourceCache/UIKit/UIKit-2380.17/UIApplication.m:2037

NSInternalInconsistencyException
@"There can only be one UIApplication instance."
Run Code Online (Sandbox Code Playgroud)

这是有道理的,那么有没有办法可以丢弃现有的单件并用新的替换它?(虽然我想如果可以的话,它不是真正的单身人士)

目的是,我不希望应用程序崩溃,给用户带来糟糕的体验.即使他们的国家没有完全恢复,我认为这仍然会比意外退出更好.

我可以尝试处理可能的预期异常,但这是尝试捕捉我没有预见到的事情.

这应该只能抓住非常不寻常的情况,所以如果不能做到这不是一件大事,但我想知道如何最好地应对这种情况.

zap*_*aph 6

这不起作用,因为异常机制在跨堆栈帧抛出时不能正确清理.由于您在main中捕获异常,因此异常已跨越多个堆栈帧.

Apple明确声明异常用于不可恢复的编程错误.

请参阅bbum的回答:"任何通过系统框架代码的异常都会使所述框架处于未定义的状态.捕获所述异常并尝试从中恢复将导致内存泄漏,未定义的行为和崩溃."
也是由bbum.

来自Apple文档:

要点:您应该保留使用异常进行编程或意外的运行时错误,例如越界收集访问,尝试改变不可变对象,发送无效消息以及丢失与窗口服务器的连接.在创建应用程序时而不是在运行时,通常会使用异常处理这些类型的错误.

  • "指导"是您无法从Objective-C中的异常中恢复,该异常跨越框架堆栈帧. (2认同)