Search code examples
iosswiftexceptionnsexception

Using NSSetUncaughtExceptionHandler in swift 4


I'm trying to use a global error handling in my project as follow:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    NSSetUncaughtExceptionHandler { (exception) in
        print(exception)
        let myView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
        let errorLabel :UILabel = UILabel(frame: CGRect(x: 10, y: (UIScreen.main.bounds.height/2) - 25 , width: UIScreen.main.bounds.width - 20 , height: 50))
        errorLabel.text = "Exception"
        myView.addSubview(errorLabel)
        self.window?.addSubview(myView)
  }
    return true
}

But I get this error while coding:

A C function pointer cannot be formed from a closure that captures context.

I searched a lot but I couldn't find any answer. Is there anything else I need to do?

UPDATE:

I found out that the problem is because I'm declaring variables inside the block. How should I handle showing a view while exception happens?


Solution

  • To summarize the above discussion: There are various problems with your approach:

    • The argument to NSSetUncaughtExceptionHandler is a C function pointer. You can pass a closure in Swift, but only if the closure does not capture any context. In your case, the closure cannot use self. The solution from How to use instance method as callback for function which takes only func or literal closure? cannot be used here because NSSetUncaughtExceptionHandler() has no “context” parameter.

    • Even if you manage to reference the application delegate in the exception handler: It can be called on any thread, so that it can be undefined behavior to call any UI related methods, such as adding views or labels.

    • NSSetUncaughtExceptionHandler catches only Objective-C exceptions, but not Swift errors (from throw) or Swift runtime exceptions (such as “unexpectedly found nil”).

    • Even if an exception is caught, you cannot “handle” it in a way that the program continues afterwards. It will still crash.

    You wrote in a comment

    I want to handle it for when I get null values from my API ... but to be on a safe side I want to prevent app from crash.

    An exception handler is not the right tool for that purpose. Use optional binding, optional casts, guards, etc to handle the response and to avoid runtime exceptions.