How to use NSSetUncaughtExceptionHandler in Swift

In Objective-C, I call the NSSetUncaughtExceptionHandler(&exceptionHandler) method to NSSetUncaughtExceptionHandler(&exceptionHandler) exceptions. What is it called in Swift?

+19
ios swift error-handling
Aug 22 '14 at 7:01
source share
4 answers

Update

With Swift 2, you can pass Swift functions and closures as a pointer to a C function. See Martin R's answer below .

Original answer

You cannot starting with Xcode 6 beta 6.

Swift supports scrolling function pointers, but they are treated almost like opaque pointers. You can neither define a pointer to a C function of a Swift function, nor call a call to a C function in Swift.

This means that you are calling NSSetUncaughtExceptionHandler() from Swift, but the handler must be implemented in Objective-C. You need a header file:

 volatile void exceptionHandler(NSException *exception); extern NSUncaughtExceptionHandler *exceptionHandlerPtr; 

and in the implementation you need something like this:

 volatile void exceptionHandler(NSException *exception) { // Do stuff } NSUncaughtExceptionHandler *exceptionHandlerPtr = &exceptionHandler; 

After importing the header file in the header of the Swift bridge, you can configure the exception handler as usual:

 NSSetUncaughtExceptionHandler(exceptionHandlerPtr) 
+13
Aug 22 '14 at 8:17
source share

Starting with Swift 2 (Xcode 7), you can pass Swift functions / closures to parameters that take a pointer to function C. From the Xcode 7 release notes:

Native support for C function pointers: C functions that take function pointer arguments can be called using closures or global functions, with the restriction that a closure should not capture any of its local context.

So this compiles and works:

 func exceptionHandler(exception : NSException) { print(exception) print(exception.callStackSymbols) } NSSetUncaughtExceptionHandler(exceptionHandler) 

Or with a "built-in" closure:

 NSSetUncaughtExceptionHandler { exception in print(exception) print(exception.callStackSymbols) } 

This does the same as the corresponding Objective-C code: it catches raw NSException . So this will be caught:

 let array = NSArray() let elem = array.objectAtIndex(99) 

NOTE: - It does not catch any Swift 2 errors (from throw ) or Swift runtime errors, so it does not catch:

 let arr = [1, 2, 3] let elem = arr[4] 
+48
02 Aug '15 at 9:22
source share

An error you may see when you reopen the next application in this way.

This code is for swift 4. Add to didFinishLaunchingWithOptions() :

 NSSetUncaughtExceptionHandler { exception in print("Error Handling: ", exception) print("Error Handling callStackSymbols: ", exception.callStackSymbols) UserDefaults.standard.set(exception.callStackSymbols, forKey: "ExceptionHandler") UserDefaults.standard.synchronize() } 

And add the code to fistViewController viewLoad()

 // ERROR ExceptionHandler if let exception = UserDefaults.standard.object(forKey: "ExceptionHandler") as? [String] { print("Error was occured on previous session! \n", exception, "\n\n-------------------------") var exceptions = "" for e in exception { exceptions = exceptions + e + "\n" } AlertFunctions.messageType.showYesNoAlert("Error was occured on previous session!", bodyMessage: exceptions, { }, no: { UserDefaults.standard.removeObject(forKey: "ExceptionHandler") UserDefaults.standard.synchronize() }) } 

EDIT: code is working. But you need to re-open the application after an error.

+4
Dec 05 '17 at 15:23
source share

Swift 5:

1. Add this method to AppDelegate:

  func storeStackTrace() { NSSetUncaughtExceptionHandler { exception in print(exception) // do stuff with the exception } } 

2. Call this method from didFinishLaunchingWithOptions and throw an exception immediately after

  func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { storeStackTrace() let exception = NSException(name: NSExceptionName(rawValue: "arbitrary"), reason: "arbitrary reason", userInfo: nil) exception.raise() } 

3. Follow the output to the console, it will immediately print the exception that you just raised, starting with the reason you specified.

0
Jul 07 '19 at 18:33
source share



All Articles