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; testez plutôt '! = nil'
Je ne veux pas vérifier 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 facultatif?
Puisque les options ne sont BooleanType
plus conformes à , le compilateur ne devrait-il pas savoir que je veux vérifier la valeur du booléen?
Réponses:
Avec des booléens facultatifs, il est nécessaire de rendre la vérification explicite:
if boolean == true { ... }
Sinon, vous pouvez déballer l'option:
if boolean! { ... }
Mais cela génère une exception d'exécution si booléen est
nil
- pour éviter que:if boolean != nil && boolean! { ... }
Avant la bêta 5, c'était possible, mais cela a été modifié comme indiqué dans les notes de publication:
Addendum: comme suggéré par @MartinR, une variante plus compacte de la 3ème option utilise l'opérateur de fusion:
if boolean ?? false { // this code runs only if boolean == true }
ce qui signifie: si booléen n'est pas nul, l'expression prend la valeur booléenne (c'est-à-dire en utilisant la valeur booléenne non emballée), sinon l'expression prend la valeur
false
la source
if let
fonctionnerait également.if boolean ?? false { ... }
.if !(boolean ?? true) { ... }
:(Reliure facultative
Swift 3 et 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
renvoiefalse
ifbooleanValue
isnil
et leif
bloc ne s'exécute pas. Si cebooleanValue
n'est pas le casnil
, ce code définit une nouvelle variable nomméebooleanValue
de typeBool
(au lieu d'un optionnel,Bool?
).Le code Swift 3 & 4
booleanValue
(et le code Swift 2.2where booleanValue
) évalue la nouvellebooleanValue: Bool
variable. Si c'est vrai, leif
bloc s'exécute avec labooleanValue: Bool
variable nouvellement définie dans la portée (permettant à l'option de référencer à nouveau la valeur liée dans leif
bloc).Remarque: C'est une convention Swift de 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 l' ombre variable . Vous pouvez rompre avec la convention et utiliser quelque chose commelet unwrappedBooleanValue = booleanValue, unwrappedBooleanValue
. Je le souligne pour aider à comprendre ce qui se passe. Je recommande d'utiliser l'ombre variable.Autres approches
Nil coalescence
Aucune fusion n'est claire pour ce cas spécifique
var booleanValue : Bool? = false if booleanValue ?? false { // executes when booleanValue is true print("optional booleanValue: '\(booleanValue)'") }
La vérification
false
n'est pas aussi clairevar booleanValue : Bool? = false if !(booleanValue ?? false) { // executes when booleanValue is false print("optional booleanValue: '\(booleanValue)'") }
Remarque:
if !booleanValue ?? false
ne compile pas.Forcer le déballage en option (à éviter)
Le déballage forcé augmente les chances que quelqu'un fasse un changement dans le futur qui se compile mais plante 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 a se
Bool?
trouvetrue
dans uneif
instruction, il est utile d'identifier une approche générale, qu'il s'agisse de vérifier la valeur true, false ou de combiner la valeur déballée avec d'autres expressions.Au fur et à mesure que l'expression se complique, je trouve l'approche de liaison facultative plus flexible et plus facile à comprendre que les autres approches. Notez que les travaux de liaison en option avec tout type en option (
Int?
,String?
, etc.).la source
if let
?while array.last < threshold { array.removeLast() }
if, let, where
utilisant ceci:while let last = array.last where last < threshold { array.removeLast() }
dans Swift 2 ouwhile let last = array.last, last < threshold { array.removeLast() }
dans Swift 3.while let
.var enabled: Bool? = true if let enabled = enabled, enabled == true { print("when is defined and true at the same moment") } if enabled ?? false { print("when is defined and true at the same moment") } if enabled == .some(true) { print("when is defined and true at the same moment") } if enabled == (true) { print("when is defined and true at the same moment") } if case .some(true) = enabled { print("when is defined and true at the same moment") } if enabled == .some(false) { print("when is defined and false at the same moment") } if enabled == (false) { print("when is defined and false at the same moment") } if enabled == .none { print("when is not defined") } if enabled == nil { print("when is not defined") }
la source
J'ai trouvé une autre solution, surchargeant les opérateurs booléens. Par exemple:
public func < <T: Comparable> (left: T?, right: T) -> Bool { if let left = left { return left < right } return false }
Cela peut ne pas être totalement dans l '«esprit» des changements de langage, mais cela permet de déballer en toute sécurité les options, et il est utilisable pour les conditions n'importe où, y compris les boucles while.
la source
La réponse que j'ai trouvée la plus facile à lire est de définir une fonction. Pas très compliqué mais fait le travail.
func isTrue(_ bool: Bool?) -> Bool { guard let b = bool else { return false } return b }
usage:
let b: Bool? = true if isTrue(b) { // b exists and is true } else { // b does either not exist or is false }
la source
Comme l'a dit Antonio
J'ai passé quelques heures à essayer de comprendre une ligne de code sur laquelle je suis tombé par hasard, mais ce fil m'a mis sur la bonne voie.
Cette citation est d' août 2014 , et depuis lors , Apple a présenté la
Never
suite proposition SE-0102 et celle- ci a rendu conforme à assimilables, HASHABLE, erreur et ComparableIl est maintenant possible de vérifier si un booléen
nil
utiliseNever?
:var boolean: Bool? = false boolean is Never? // false boolean = true boolean is Never? // false boolean = nil boolean is Never? // true
Vous pouvez en fait utiliser tout autre type inhabitable :
public enum NeverEver { } var boolean: Bool? = false boolean is NeverEver? // false boolean = true boolean is NeverEver? // false boolean = nil boolean is NeverEver? // true
Cela étant dit, il est également possible d'utiliser un wrapper de propriété maintenant:
@propertyWrapper struct OptionalBool { public var wrappedValue: Bool? public var projectedValue: Bool { wrappedValue ?? false } public init(wrappedValue: Bool?) { self.wrappedValue = wrappedValue } } struct Struct { @OptionalBool var predicate: Bool? var description: String { if $predicate { return "predicate is true" } return "predicate is false" } } var object = Struct() object.description // "predicate is false" object.predicate = false object.description // "predicate is false" object.predicate = true object.description // "predicate is true"
ou même:
@propertyWrapper struct OptionalBool { var wrappedValue: Bool? var projectedValue: OptionalBool { self } var isNil: Bool { wrappedValue is Never? } var value: Bool { wrappedValue ?? false } init(wrappedValue: Bool?) { self.wrappedValue = wrappedValue } } struct Struct { @OptionalBool var predicate: Bool? var description: String { if $predicate.value { return "predicate is true" } if !$predicate.isNil { return "predicate is false" } return "predicate is nil" } } var object = Struct() object.description // "predicate is nil" object.predicate = false object.description // "predicate is false" object.predicate = true object.description // "predicate is true"
la source