swift - Comprobando el valor de un Bool opcional
boolean optional (3)
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 puede ser usado como un booleano; prueba para ''! = nil'' en su lugar
No quiero comprobar si hay cero; Quiero comprobar si el valor devuelto es verdadero.
¿Siempre tengo que hacer if boolean == true
si estoy trabajando con un Bool opcional?
Dado que Optionals ya no se ajusta a BooleanType
, ¿no debería saber el compilador que quiero verificar el valor de Bool?
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 = booleanValue
devuelva false
si booleanValue
es nil
y el bloque if
no se ejecuta. Si booleanValue
no es nil
, este código define una nueva variable llamada booleanValue
de tipo Bool
(en lugar de una opcional, Bool?
).
El código Swift 3 y 4 booleanValue
(y el código Swift 2.2 where booleanValue
) evalúa la nueva variable booleanValue: Bool
. Si es verdadero, el bloque if
se ejecuta con la variable booleanValue: Bool
recién definida en el alcance (permitiendo que la opción vuelva a hacer referencia al valor límite dentro del bloque if
).
Nota: es una convención Swift el nombre de la constante / variable vinculada igual que la constante / variable opcional, como let booleanValue = booleanValue
. Esta técnica se llama sombreado variable . Podrías romper con la convención y usar algo como let unwrappedBooleanValue = booleanValue, unwrappedBooleanValue
. Señalo esto para ayudar a entender lo que está sucediendo. Recomiendo el uso de sombreado variable.
Otros enfoques
Nil uniendo
Nil coalescente está claro para este caso específico.
var booleanValue : Bool? = false
if booleanValue ?? false {
// executes when booleanValue is true
print("optional booleanValue: ''/(booleanValue)''")
}
Comprobar si es false
no es tan claro
var booleanValue : Bool? = false
if !(booleanValue ?? false) {
// executes when booleanValue is false
print("optional booleanValue: ''/(booleanValue)''")
}
Nota: if !booleanValue ?? false
if !booleanValue ?? false
no compila
Fuerza de desenvolvimiento opcional (evitar)
El desenvolvimiento de la fuerza aumenta la posibilidad de que alguien realice un cambio en el futuro que compile pero se bloquee en el 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 un Bool?
es true
dentro de una sentencia if
, es útil identificar un enfoque general ya sea que se verifique si es verdadero, falso o si se combina el valor no envuelto 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 el enlace opcional funciona con cualquier tipo opcional ( Int?
String?
Etc.).
Con booleanos opcionales es necesario hacer el cheque explícito:
if boolean == true {
...
}
De lo contrario puedes desenvolver el opcional:
if boolean! {
...
}
Pero eso genera una excepción de tiempo de ejecución si boolean es nil
, para evitar que:
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:
Los opcionales ya no se evalúan implícitamente en verdadero cuando tienen un valor y falso cuando no lo tienen, para evitar confusiones cuando se trabaja con valores Bool opcionales. En su lugar, realice una comprobación explícita contra nil con los operadores == o! = Para averiguar si un opcional contiene un valor.
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 nulo, la expresión se evalúa al valor booleano (es decir, utiliza el valor booleano no envuelto); de lo contrario, la expresión se evalúa como false
Encontré otra solución, sobrecargando a los operadores booleanos. Por ejemplo:
public func < <T: Comparable> (left: T?, right: T) -> Bool {
if let left = left {
return left < right
}
return false
}
Es posible que esto no esté totalmente en el "espíritu" de los cambios de lenguaje, pero permite el desenvolvimiento seguro de las opciones, y se puede usar para condicionales en cualquier lugar, incluidos los bucles while.