在Objective-C中,我调用NSSetUncaughtExceptionHandler(&exceptionHandler)
方法来记录异常。在Swift中该如何调用?
在Objective-C中,我调用NSSetUncaughtExceptionHandler(&exceptionHandler)
方法来记录异常。在Swift中该如何调用?
从Swift 2(Xcode 7)开始,您可以将Swift函数/闭包传递给接受C函数指针的参数。来自Xcode 7发布说明:
C函数指针的本地支持:使用闭包或全局函数调用带有函数指针参数的C函数,但限制是该闭包不能捕获其本地上下文。
因此,以下代码将编译并运行:
func exceptionHandler(exception : NSException) {
print(exception)
print(exception.callStackSymbols)
}
NSSetUncaughtExceptionHandler(exceptionHandler)
或者使用“内联”闭包:
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 2中,你可以将Swift函数和闭包传递作为C函数指针。请查看下面Martin R的回答.
在Xcode 6 beta 6中,你不能这样做。
Swift确实支持传递函数指针,但它们几乎像不透明指针一样处理。你既不能定义一个C函数指针来调用Swift函数,也不能在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桥接头文件之后,您可以像往常一样设置异常处理程序:
NSSetUncaughtExceptionHandler(exceptionHandlerPtr)
.h
/.m
文件对异常处理器进行实现,然后将其头文件导入到桥接头文件中。 - jouSwift 5:
1. 将此方法添加到AppDelegate中:
func storeStackTrace() {
NSSetUncaughtExceptionHandler { exception in
print(exception)
// do stuff with the exception
}
}
2. 在didFinishLaunchingWithOptions方法中调用此方法,并在立即引发异常
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. 跟踪控制台输出,它会立即打印出你刚刚提供的异常原因开始的异常信息。
didFinishLaunchingWithOptions()
中添加以下内容:NSSetUncaughtExceptionHandler { exception in
print("Error Handling: ", exception)
print("Error Handling callStackSymbols: ", exception.callStackSymbols)
UserDefaults.standard.set(exception.callStackSymbols, forKey: "ExceptionHandler")
UserDefaults.standard.synchronize()
}
将以下代码添加到firstViewController的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()
})
}
编辑:代码可行。但是在出现错误后需要重新打开应用程序。
exception.callStackSymbols.joinWithSeparator("\n")
。 - Pavel Alexeev