我应该如何在Swift中使用NSSetUncaughtExceptionHandler

在Objective-C中,我调用NSSetUncaughtExceptionHandler(&exceptionHandler)方法来loggingexception。 它如何在Swift中调用?

更新

在Swift 2中,可以将Swift函数和闭包作为C函数指针传递。 请参阅下面的Martin R的答案 。

原始答案

你不能,如Xcode 6testing版6。

Swift确实支持传递函数指针,但是它们看起来很像不透明的指针。 你既不能定义一个Swift函数的C函数指针,也不能在Swift中调用C函数指针。

这意味着你可以从Swift调用NSSetUncaughtExceptionHandler() ,但是处理程序必须在Objective-C中实现。 你需要一个像这样的头文件:

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

在实现中,你需要这样的东西:

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

在Swift桥接头文件中导入头文件之后,可以照常设置exception处理程序:

 NSSetUncaughtExceptionHandler(exceptionHandlerPtr) 

从Swift 2(Xcode 7)开始,可以将Swift函数/闭包传递给带有C函数指针的参数。 从Xcode 7发行说明:

对C函数指针的本地支持:可以使用闭包或全局函数来调用带有函数指针参数的C函数,限制条件是闭包不能捕获任何本地上下文。

所以这个编译和工作:

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

或者“内联”closures:

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

这与相应的Objective-C代码完全相同:捕获否则未捕获的NSException 。 所以这会被抓住:

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

它不捕获任何Swift 2错误(从throw )或Swift运行时错误,所以这不被捕获:

 let arr = [1, 2, 3] let elem = arr[4] 

您可以通过这种方式在后续应用程序的开始处看到错误。

这个代码为swift 4.添加在didFinishLaunchingWithOptions()

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

和代码添加在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() }) }