Le message d'erreur est assez explicite. Le runtime s'attendait à ne pas trouver de nil lors du déballage d'une variable optionnelle que vous avez créée, mais en a trouvé un à cet endroit, invalidant ainsi tout le code qui vient après cette ligne, donc l'application s'est plantée.
En forme encore plus longue : Vous avez fait une promesse au compilateur et vous ne l'avez pas respectée. Vous avez dit au compilateur que vous étiez certain que votre variable serait non-nil au moment de son accès, et ensuite le compilateur a prouvé que vous étiez un gros menteur. Vous avez fait cette promesse en utilisant l'opérateur you-should-practically-neve-use-this, le " bang ", qui ressemble à ceci : !
L'opérateur bang est utilisé pour désigner une option explicitement déballée, ou une option déballée de force. C'est-à-dire qu'il s'agit d'une variable de type optionnel (c'est-à-dire qu'elle peut ou non être nil) pour laquelle vous, en tant que programmeur, faites la promesse au compilateur qu'elle ne sera pas nil au moment de son accès.
Cela se produit soit au moment de la déclaration de la variable, comme ceci:
- var myNecessaryInt : Int !
soit au moment de l'accès, comme ceci:
- var myNecessaryInt : Int ?
- let myNecessaryString = "(myNecessaryInt !)"
Dans ce dernier cas, cela revient moins à rompre une promesse qu'à dire à la dernière minute : " Faites-moi confiance ! Je sais que c'est là ! Est-ce que je vous mentirais ?"
Cette erreur n'est rencontrée que lorsque quelqu'un a eu l'impression que l'utilisation de if let ou guard let était un énorme tracas ou une perte de temps flagrante. Plutôt que d'utiliser une construction simple qui rendrait leur code sûr, ils ont choisi de supposer que leur cerveau humain ordinaire pourrait facilement penser à tous les scénarios possibles et à tous les moments où l'on pourrait accéder à une variable. The solution: trust the tools of the language and write safe code rather than writing less code.
In both examples above, simply architecting the file so that the method accessing the optional could either exit early (if it’s a method that returns Void):
- var myNecessaryInt: Int?
- func doSomeStuffWithMyInt() {
- guard let necessaryInt = myNecessaryInt else {
- return
- }
- let theStringVersion = “(necessaryInt)”
- // and so on...
or that throws an error in the case that the variable is nil:
- var myNecessaryInt: Int?
- func doSomeStuffWithMyInt() throws {
- guard let necessaryInt = myNecessaryInt else {
- throw NSError(domain: "com.myApp",
- code: 0,
- userInfo: ["description": "The number wasn't there."])
- }
- let theStringVersion = “(necessaryInt)”
- // and so on...
Quoi qu'il en soit, si vous écrivez du code Swift stable et sûr, alors dans 99,999% des cas vous éviterez d'utiliser !
Sur la raison pour laquelle il plante sur cette erreur avec SwiftUI, la seule chose à laquelle je peux penser est qu'une option explicitement déballée est utilisée quelque part dans votre fichier SwiftUI. Peut-être que l'objet modèle qui le soutient est un optionnel à déballage forcé, ou qu'il est introduit dans la variable d'état liée à la vue ? Quoi qu'il en soit, lorsque l'erreur est lancée, elle devrait capturer le nom du fichier et le numéro de la ligne, et si vous ajoutez un point d'arrêt d'exception dans Xcode, elle devrait même s'arrêter sur cette ligne et vous permettre d'inspecter les variables disponibles à la portée de la ligne incriminée.