我应该如何在Swift中使用NSSetUncaughtExceptionHandler

时间:2014-08-22 07:01:13

标签: ios swift error-handling

在Objective-C,我调用NSSetUncaughtExceptionHandler(&exceptionHandler)方法来记录异常。它是如何在Swift中调用的?

4 个答案:

答案 0 :(得分:47)

从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]

答案 1 :(得分:13)

更新

使用Swift 2,您可以将Swift函数和闭包作为C函数指针传递。 See Martin R's answer below

原始答案

您不能使用Xcode 6 beta 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桥接头中导入头文件后,您可以照常设置异常处理程序:

NSSetUncaughtExceptionHandler(exceptionHandlerPtr)

答案 2 :(得分:2)

以这种方式重新打开后续应用程序时可以看到的错误。

此代码适用于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()
            })
        }

编辑: 代码工作。但是您需要在出错后重新打开应用程序。

答案 3 :(得分:0)

快捷键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。跟进控制台输出,它将立即从您提供的原因开始打印出刚提出的异常。