Swift中未捕获的错误/异常处理

Sun*_*mbi 11 uncaughtexceptionhandler swift

我知道Cocoa中有一个UncaughtExceptionHandler,但我正在为Swift寻找同样的东西.即,当应用程序中由于任何错误而未在本地捕获任何错误/异常时,它应该一直冒泡到顶级应用程序对象,在那里我应该能够优雅地处理它并适当地响应用户.

Android拥有它.Flex有它.Java有它.想知道Swift为什么缺少这个关键功能.

and*_*rei 12

这是我用来记录所有异常/错误的代码.Log.error(with:)是一个自定义函数,我存储堆栈跟踪以及其他信息.Thread.callStackSymbols是一个字符串数组,表示堆栈跟踪.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {

    NSSetUncaughtExceptionHandler { exception in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGABRT) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGILL) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGSEGV) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGFPE) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGBUS) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGPIPE) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    return true
}
Run Code Online (Sandbox Code Playgroud)

  • 请注意,只有“异步信号安全”功能可以从信号处理程序中安全调用。“ printf”和相关功能不是异步信号安全的。 (2认同)

Mar*_*n R 11

Swift没有机制来捕获所有任意运行时异常.原因在于解释

在swift-users论坛中.提取:

Swift有意识地选择不包括通过任意堆栈帧抛出的异常,不是因为它在技术上是不可能的,而是因为它的设计者认为成本过高.

问题是:如果一段代码由于错误而提前退出,则必须编写它以处理提前退出.否则它会行为错误 - 无法释放内存,无法关闭文件句柄/套接字/数据库连接/无论如何,无法释放锁等等.在像Java这样的语言中,编写真正的异常安全代码需要大量的try/finally块.这就是为什么没有人这样做的原因.他们判断他们可能会看到哪些例外情况以及泄漏哪些资源是危险的,并且只保护他们的代码免受那些特定的预期条件的影响.然后发生了无法预料的事情并且他们的程序中断了.

在像Swift这样的引用计数语言中,情况更糟,因为在存在异常时正确平衡引用计数基本上要求每个函数都包含一个隐式finally块来平衡所有保留计数.这意味着编译器必须在一些调用或另一个调用异常的情况下生成大量额外代码.绝大多数代码永远不会被使用,但它必须在那里,使这个过程膨胀.

由于这些问题,Swift选择不支持传统的例外; 相反,它只允许您在特殊标记的代码区域中抛出错误.但作为必然结果,这意味着,如果在无法抛出的代码中出现问题,那么它所能真正做到的就是防止灾难崩溃.目前,唯一可以崩溃的是整个过程.

有关更多信息,请参阅

  • 这对我很好,但我仍然需要至少能够捕获信号,以便我可以实现我的崩溃记录器.似乎无法使它工作; 强制展开nil抛出一个'EXC_BAD_INSTRUCTION`,我无法捕获异常或信号处理程序...... (3认同)
  • 谢谢@MartinR ......我发现Swift的人已经卸下了"按设计"处理开发人员的每一个小或大的异常和错误的负担. (2认同)