web-dev-qa-db-fra.com

Comment utiliser NSSetUncaughtExceptionHandler dans Swift?

En Objective-C, j'appelle la méthode NSSetUncaughtExceptionHandler(&exceptionHandler) pour consigner les exceptions. Comment ça s'appelle à Swift?

17
billy

Mettre à jour

Avec Swift 2, vous pouvez transmettre des fonctions et des fermetures Swift en tant que pointeur de fonction C. Voir la réponse de Martin R ci-dessous .

Réponse originale

Vous ne pouvez pas, à partir de Xcode 6 beta 6.

Swift prend en charge le transfert des pointeurs de fonction, mais ils sont traités à peu près comme des pointeurs opaques. Vous ne pouvez pas non plus définir un pointeur de fonction C sur une fonction Swift, ni appeler un pointeur de fonction C dans Swift.

Cela signifie que vous appelez NSSetUncaughtExceptionHandler() depuis Swift, mais que le gestionnaire doit être implémenté dans Objective-C. Vous avez besoin d'un fichier d'en-tête comme ceci:

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

et dans la mise en œuvre, vous avez besoin de quelque chose comme ceci:

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

Après avoir importé le fichier d'en-tête dans l'en-tête de pontage Swift, vous pouvez configurer le gestionnaire d'exceptions comme d'habitude:

NSSetUncaughtExceptionHandler(exceptionHandlerPtr)
13
jou

À partir de Swift 2 (Xcode 7), vous pouvez passer les fonctions/fermetures Swift Aux paramètres prenant un pointeur de fonction C. À partir des notes de publication de Xcode 7:

Prise en charge native des pointeurs de fonction C: les fonctions C prenant des arguments de pointeur de fonction Peuvent être appelées à l'aide de fermetures ou de fonctions globales, , avec la restriction que la fermeture ne doit capturer aucun de ses . contexte local.

Donc, cela compile et fonctionne:

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

NSSetUncaughtExceptionHandler(exceptionHandler)

Ou avec une fermeture "en ligne":

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

Cela fait exactement la même chose que le code Objective-C correspondant: Il capture par ailleurs NSExceptions non capturé. Ce sera donc capturé:

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

NOTE: - Il ne pas intercepte les erreurs Swift 2 (de throw) ou les erreurs d'exécution Swift, elles ne sont donc pas interceptées:

let arr = [1, 2, 3]
let elem = arr[4]
45
Martin R

L'erreur que vous pouvez voir lors de la réouverture d'une application ultérieure de cette manière.

Ce code pour Swift 4. Ajouter dans didFinishLaunchingWithOptions():

NSSetUncaughtExceptionHandler { exception in
            print("Error Handling: ", exception)
            print("Error Handling callStackSymbols: ", exception.callStackSymbols)

            UserDefaults.standard.set(exception.callStackSymbols, forKey: "ExceptionHandler")
            UserDefaults.standard.synchronize()
        }

Et le code ajouté dans 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: Le code fonctionne. Mais vous devez rouvrir votre application après une erreur.

2
Yunus T.