web-dev-qa-db-fra.com

Swift bonne pratique de codage: Instruction If avec le type optionnel Bool

J'ai donc développé une application dans Swift et aujourd'hui, j'ai passé près d'une heure à déboguer un problème complètement inattendu. Tout résulte du code ci-dessous.

if (hero.isAI) { //isAI is a Bool

}

Le problème était que cette instruction if retournait TOUJOURS la valeur true. Je pensais donc que je mettais peut-être à isAI une valeur true, mais je me suis finalement rendu compte que j’ai déclaré isAI comme type facultatif, comme indiqué ci-dessous.

var isAI: Bool!

quand cela aurait dû être

var isAI: Bool

Cela a eu pour résultat que l'instruction if n'a pas vérifié si isAI était vrai, mais a vérifié si elle contenait une valeur.

Donc, pour être en sécurité maintenant, je m'assure d'écrire mes if-déclarations comme ceci 

if (hero.isAI == true) { //isAI is a Bool

}

Donc ma question est, quelles sont mes options pour éviter ce problème à l'avenir? (ce problème semble extrêmement dangereux, en particulier lorsque vous travaillez en équipe sur un grand projet). Devrais-je toujours écrire explicitement mon if-déclaration, dois-je simplement éviter le type optionnel pour Bools?

Notez que je n'ai pas eu ce problème dans Xcode Beta 2. Ce problème est survenu lors de la mise à niveau vers Xcode beta 3. Je pense que, dans la version bêta 2, Apple traitait implicitement Bool dans une instruction if en vérifiant sa valeur plutôt qu'en vérifiant si elle contient une valeur.

Enfin, vous trouverez ci-dessous un exemple des instructions if exécutées avec un booléen facultatif afin de mieux aider les gens à comprendre le problème.

let myBool: Bool! = false

if (myBool) {
    //Runs
}

if (myBool!) {
    //Won't Run
}

if (!myBool) {
    //Runs
}

if (myBool == true) {
    //Won't Run
}
11
Epic Byte

Il s'agit d'un problème connu qui fait l'objet d'un suivi sur SwiftInFlux repo, qui inclut cette citation de Chris Lattner sur les forums de développement Apple .

Ce problème existe avec toute option de quelque chose qui est conforme à Le protocole LogicValue (par exemple des options imbriquées, optionnel de bool, Etc.). Nous estimons qu’un problème grave doit être résolu pour 1.0 et que A des idées, mais qu’il n’a pas encore trouvé de solution.

Ainsi, ce problème ne concerne pas uniquement les Bool facultatifs, mais tout type facultatif conforme au protocole LogicValue (défini comme).

protocol LogicValue {
    func getLogicValue() -> Bool
}

Quoi qu'il en soit, en ce qui concerne les recommandations sur la manière de contourner ce problème, il est difficile de recommander une solution spécifique, car Apple n'a pas indiqué comment ils entendent résoudre ce problème à l'avenir, mais j'imagine que continuer à vérifier de manière explicite la valeur du Bool serait la voie à suivre.

if (hero.isAI == true) {
    // stuff    
}

En fait, après quelques lectures supplémentaires, la citation mentionnée ci-dessus continue à se lire:

Pour ce cas courant, la réponse la plus simple serait de produire un avertissement Pour "si x" et de demander à quelqu'un d'écrire explicitement "si x! = Nil" ou "si x == vrai". pour le rendre explicite ce qu'ils veulent.

11
Mick MacCallum

mon conseil est d'utiliser ce Nice coalescent ??

if textfieldDate.text?.isEmpty ?? true {
    // the text is either nil or empty but its all we want to know
}
3
Nicolas Manzini

Si le booléen fait partie de Core Data (aussi appelé NSNumber), vous devriez le faire comme ceci.

if (isHero.isAI?.boolValue != nil)

Cordialement

0
Cristian Pena