Cuando quiero verificar si un bool opcional es verdadero, hacer esto no funciona:
var boolean : Bool? = false
if boolean{
}
Resulta en este error:
Tipo opcional '@IvalueBool?' no se puede utilizar como booleano; prueba para '! = nil' en su lugar
No quiero comprobar nada; Quiero comprobar si el valor devuelto es verdadero.
¿Tengo que hacerlo siempre if boolean == truesi estoy trabajando con un bool opcional?
Dado que los opcionales ya no se ajustan BooleanType, ¿no debería saber el compilador que quiero verificar el valor de Bool?

Respuestas:
Con booleanos opcionales, es necesario hacer la verificación explícita:
if boolean == true { ... }De lo contrario, puede desenvolver el opcional:
if boolean! { ... }Pero eso genera una excepción de tiempo de ejecución si boolean es
nil, para evitar eso:if boolean != nil && boolean! { ... }Antes de la beta 5 era posible, pero se ha cambiado como se informa en las notas de la versión:
Anexo: como lo sugiere @MartinR, una variación más compacta de la tercera opción es usar el operador coalescente:
if boolean ?? false { // this code runs only if boolean == true }lo que significa: si booleano no es nil, la expresión se evalúa como el valor booleano (es decir, utilizando el valor booleano no envuelto); de lo contrario, la expresión se evalúa como
falsefuente
if lettambién funcionaría.if boolean ?? false { ... }.if !(boolean ?? true) { ... }:(Enlace opcional
Swift 3 y 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)'") }El código
let booleanValue = booleanValuedevuelvefalsesibooleanValueesnily elifbloque no se ejecuta. SibooleanValueno es asínil, este código define una nueva variable denominadabooleanValuede tipoBool(en lugar de opcionalBool?).El código Swift 3 y 4
booleanValue(y el código Swift 2.2where booleanValue) evalúa la nuevabooleanValue: Boolvariable. Si es cierto, elifbloque se ejecuta con labooleanValue: Boolvariable recién definida en el alcance (lo que permite que la opción haga referencia al valor enlazado nuevamente dentro delifbloque).Nota: Es una convención de Swift nombrar la constante / variable ligada de la misma manera que la constante / variable opcional como
let booleanValue = booleanValue. Esta técnica se denomina sombreado variable . Podrías romper con las convenciones y usar algo comolet unwrappedBooleanValue = booleanValue, unwrappedBooleanValue. Señalo esto para ayudar a comprender lo que está sucediendo. Recomiendo usar sombreado variable.Otros enfoques
Nil coalescencia
La fusión nula es clara para este caso específico
var booleanValue : Bool? = false if booleanValue ?? false { // executes when booleanValue is true print("optional booleanValue: '\(booleanValue)'") }La comprobación
falseno es tan claravar booleanValue : Bool? = false if !(booleanValue ?? false) { // executes when booleanValue is false print("optional booleanValue: '\(booleanValue)'") }Nota:
if !booleanValue ?? falseno se compila.Forzar desenvolver opcional (evitar)
Forzar el desenvolvimiento aumenta la posibilidad de que alguien haga un cambio en el futuro que compila pero falla en tiempo de ejecución. Por lo tanto, evitaría algo como esto:
var booleanValue : Bool? = false if booleanValue != nil && booleanValue! { // executes when booleanValue is true print("optional booleanValue: '\(booleanValue)'") }Un enfoque general
Aunque esta pregunta de desbordamiento de pila pregunta específicamente cómo verificar si a
Bool?estátruedentro de unaifdeclaración, es útil identificar un enfoque general, ya sea verificar verdadero, falso o combinar el valor sin envolver con otras expresiones.A medida que la expresión se vuelve más complicada, encuentro que el enfoque de enlace opcional es más flexible y más fácil de entender que otros enfoques. Tenga en cuenta que las obras de enlace opcionales con cualquier tipo opcional (
Int?,String?, etc.).fuente
if let?while array.last < threshold { array.removeLast() }if, let, whereusando esto:while let last = array.last where last < threshold { array.removeLast() }en Swift 2 owhile let last = array.last, last < threshold { array.removeLast() }en 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") }fuente
Encontré otra solución, sobrecargando los operadores booleanos. Por ejemplo:
public func < <T: Comparable> (left: T?, right: T) -> Bool { if let left = left { return left < right } return false }Esto puede no estar totalmente en el "espíritu" de los cambios de lenguaje, pero permite desenvolver de forma segura los opcionales y se puede utilizar para los condicionales en cualquier lugar, incluidos los bucles while.
fuente
La respuesta que encontré más fácil de leer es definir una función. No es muy complicado, pero funciona.
func isTrue(_ bool: Bool?) -> Bool { guard let b = bool else { return false } return b }uso:
let b: Bool? = true if isTrue(b) { // b exists and is true } else { // b does either not exist or is false }fuente
Como dijo Antonio
Pasé algunas horas tratando de entender una línea de código con la que me topé, pero este hilo me puso en el camino correcto.
Esta cita es de agosto de 2014 y, desde entonces, Apple presentó la
Neversiguiente propuesta SE-0102 y la hizo cumplir con Equatable, Hashable, Error y Comparable.Ahora es posible verificar si un booleano está
nilusandoNever?:var boolean: Bool? = false boolean is Never? // false boolean = true boolean is Never? // false boolean = nil boolean is Never? // trueDe hecho, puede usar cualquier otro tipo inhabitable :
public enum NeverEver { } var boolean: Bool? = false boolean is NeverEver? // false boolean = true boolean is NeverEver? // false boolean = nil boolean is NeverEver? // trueDicho esto, también es posible usar un contenedor de propiedades ahora:
@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"o incluso:
@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"fuente