swift boolean optional

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.