with - try catch swift 4




Gestion des erreurs/exceptions non détectées dans Swift (2)

C'est le code que j'utilise pour consigner toutes les exceptions / erreurs. Log.error(with:) est une fonction personnalisée dans laquelle je stocke la trace de la pile, ainsi que d'autres informations. Thread.callStackSymbols est un tableau de chaînes et représente la trace de la pile.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]? = nil) -> Bool {

    NSSetUncaughtExceptionHandler { exception in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGABRT) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGILL) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGSEGV) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGFPE) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGBUS) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    signal(SIGPIPE) { _ in
        Log.error(with: Thread.callStackSymbols)
    }

    return true
}

Je sais qu’il existe un UncaughtExceptionHandler dans Cocoa, mais je cherche la même chose pour Swift. C'est-à-dire que chaque fois qu'il y a une erreur / exception dans une application qui n'est pas localisée localement à cause d'une erreur, elle devrait s'afficher jusqu'à l'objet d'application de niveau supérieur où je devrais être capable de la gérer avec élégance et de répondre de manière appropriée à l'utilisateur.

Android a. Flex a. Java a. Vous vous demandez pourquoi Swift manque cette fonctionnalité clé.


Swift ne dispose d'aucun mécanisme pour intercepter toutes les exceptions d'exécution arbitraires. Les raisons sont expliquées dans

dans le forum swift-users. Extrait:

Swift a fait le choix conscient de ne pas inclure les exceptions générées par des cadres de pile arbitraires, non pas parce que c'était techniquement impossible, mais parce que ses concepteurs ont estimé que les coûts étaient trop élevés.

Le problème est le suivant: si un élément de code doit sortir tôt à cause d'une erreur, il doit être écrit pour gérer cette sortie précoce. Sinon, il se comportera mal - échec de libération de la mémoire, fermeture des descripteurs de fichier / sockets / connexions de base de données / quoi que ce soit, absence de libération des verrous, etc. des blocs. C'est pourquoi personne ne le fait. Ils déterminent quelles exceptions ils sont susceptibles de voir et quelles ressources sont dangereuses de fuir, et ne protègent leur code que contre ces conditions anticipées spécifiques. Ensuite, il se passe quelque chose d'imprévu et leur programme se termine.

Ceci est encore pire dans un langage à comptage de références tel que Swift, car équilibrer correctement les comptages de références en présence d'exceptions requiert essentiellement que chaque fonction inclue un bloc final implicite pour équilibrer tous les comptages conservés. Cela signifie que le compilateur doit générer beaucoup de code supplémentaire au cas où un appel ou un autre lève une exception. La grande majorité de ce code n'est jamais, jamais utilisé, mais il doit être là, bouleversant le processus.

En raison de ces problèmes, Swift a choisi de ne pas accepter les exceptions traditionnelles. à la place, cela vous permet uniquement de générer des erreurs dans des régions de code spécialement marquées. Mais corollairement, cela signifie que, si quelque chose ne va pas dans le code qui ne peut pas être jeté, tout ce qu'il peut vraiment faire pour empêcher un sinistre est de planter. Et pour le moment, la seule chose que vous pouvez bloquer est l’ensemble du processus.

Pour plus d'informations, voir





uncaughtexceptionhandler