web-dev-qa-db-fra.com

Vérification de la valeur d'un bool optionnel

Lorsque je veux vérifier si un booléen facultatif est vrai, cela ne fonctionne pas:

var boolean : Bool? = false
if boolean{
}

Il en résulte cette erreur:

Type facultatif '@IvalueBool?' ne peut pas être utilisé comme booléen; test pour '! = nil' à la place

Je ne veux pas vérifier pour zéro; Je veux vérifier si la valeur renvoyée est vraie.

Dois-je toujours faire if boolean == true si je travaille avec un Bool optionnel?

Puisque les options ne sont plus conformes à BooleanType, le compilateur ne devrait-il pas savoir que je veux vérifier la valeur du booléen?

75
Moon Cat

Avec des booléens optionnels, il est nécessaire de rendre la vérification explicite:

if boolean == true {
    ...
}

Sinon, vous pouvez ouvrir l’option facultative:

if boolean! {
    ...
}

Mais cela génère une exception d’exécution si booléen est nil - pour éviter cela:

if boolean != nil && boolean! {
    ...
}

Avant la version 5, c'était possible, mais cela a été modifié comme indiqué dans les notes de version:

Les options ne sont plus implicitement évaluées sur true lorsqu'elles ont une valeur et sur false si elles ne le sont pas, afin d'éviter toute confusion lors de l'utilisation de valeurs Bool optionnelles. Au lieu de cela, faites une vérification explicite sur nil avec les opérateurs == ou! = Pour déterminer si un facultatif contient une valeur.

Addendum: comme suggéré par @MartinR, une variante plus compacte de la 3ème option utilise l'opérateur de coalescence:

if boolean ?? false {
    // this code runs only if boolean == true
}

ce qui signifie que si booléen n'est pas nil, l'expression est évaluée à la valeur booléenne (c'est-à-dire en utilisant la valeur booléenne non enveloppée), sinon l'expression est évaluée à false

172
Antonio

Reliure optionnelle

Swift 3 & 4

var booleanValue : Bool? = false
if let booleanValue = booleanValue, booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

Swift 2.2

var booleanValue : Bool? = false
if let booleanValue = booleanValue where booleanValue {
    // Executes when booleanValue is not nil and true
    // A new constant "booleanValue: Bool" is defined and set
    print("bound booleanValue: '\(booleanValue)'")
}

Le code let booleanValue = booleanValue Renvoie false si booleanValue est nil et que le bloc if ne s'exécute pas. Si booleanValue n'est pas nil, ce code définit une nouvelle variable nommée booleanValue de type Bool (au lieu d'un optionnel, Bool?) .

Le code Swift 3 & 4 booleanValue (et le code Swift 2.2 where booleanValue) Évalue la nouvelle variable booleanValue: Bool. Si c'est le cas, le bloc if s'exécute avec la variable booleanValue: Bool Nouvellement définie (permettant à l'option de référencer à nouveau la valeur liée dans le bloc if.).

Remarque: la convention Swift consiste à nommer la constante/variable liée de la même manière que la constante/variable optionnelle telle que let booleanValue = booleanValue. Cette technique s'appelle observation variable. Vous pouvez rompre avec la convention et utiliser quelque chose comme let unwrappedBooleanValue = booleanValue, unwrappedBooleanValue. Je signale cela pour aider à comprendre ce qui se passe. Je recommande d'utiliser l'observation variable.

Autres approches

Néant coalescent

La coalescence nulle est claire pour ce cas particulier

var booleanValue : Bool? = false
if booleanValue ?? false {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

Vérifier false n'est pas aussi clair

var booleanValue : Bool? = false
if !(booleanValue ?? false) {
    // executes when booleanValue is false
    print("optional booleanValue: '\(booleanValue)'")
}

Remarque: if !booleanValue ?? false Ne compile pas.

Déballage forcé facultatif (à éviter)

Le déploiement forcé augmente les chances que quelqu'un effectue un changement qui compile mais se bloque au moment de l'exécution. Par conséquent, j'éviterais quelque chose comme ceci:

var booleanValue : Bool? = false
if booleanValue != nil && booleanValue! {
    // executes when booleanValue is true
    print("optional booleanValue: '\(booleanValue)'")
}

Une approche générale

Bien que cette question de débordement de pile demande spécifiquement comment vérifier si un Bool? Correspond à true dans une instruction if, il est utile de définir une approche générale consistant à rechercher la valeur true, false ou à combiner la valeur non emballée avec d'autres expressions.

Au fur et à mesure que l’expression devient plus compliquée, je trouve l’approche facultative obligatoire plus souple et plus facile à comprendre que d’autres approches. Notez que la liaison facultative fonctionne avec n'importe quel type facultatif (Int?, String?, Etc.).

38
Mobile Dan