Decoraciones rápidas y variables con "?" (signo de interrogación) y "!" (signo de exclamación)

106

Entiendo que en Swift todas las variables deben establecerse con un valor, y que al usar opcionales podemos establecer una variable que se establecerá nilinicialmente.

Lo que no entiendo es qué !está haciendo la configuración de una variable con a , porque tenía la impresión de que esto "desenvuelve" un valor de un opcional. Pensé que al hacerlo, estás garantizando que hay un valor para desenvolver en esa variable, por lo que en IBActions y demás lo ves usado.

En pocas palabras, ¿cuál es la variable que se inicializa cuando haces algo como esto?

var aShape : CAShapeLayer!

¿Y por qué / cuándo haría esto?

Jason Renaldo
fuente
Debería hacer esto para saber que una variable no es nula después de verificar este hecho.
Matthias
No creo que esto deba marcarse como un duplicado. "¿Qué es un opcional?" no es la misma pregunta que "¿Cuál es la diferencia entre los dos tipos de opcionales?" que es más o menos lo que es esta pregunta
Jiaaro
@Jiaaro, incluso en ese caso, ya hay toneladas de preguntas sobre opcionales, opcionales sin envolver implícitamente y cosas por el estilo. También puede consultar este: stackoverflow.com/questions/24272781/…
Jack
@JackWu Ok, pero estoy bastante seguro de que esta pregunta no era un duplicado cuando se hizo. (se preguntó una semana antes de su ejemplo, por ejemplo)
Jiaaro
@Jiaaro Tienes un buen punto, no me di cuenta de que esto era más antiguo ... tal vez el otro debería estar marcado como un duplicado de este en su lugar ..
Jack

Respuestas:

145

En una declaración de tipo, el !es similar al ?. Ambos son opcionales, pero !es un opcional " implícitamente desenvuelto " , lo que significa que no es necesario desenvolverlo para acceder al valor (pero aún puede ser nulo).

Este es básicamente el comportamiento que ya teníamos en objetivo-c. Un valor puede ser nulo, y debe verificarlo, pero también puede acceder al valor directamente como si no fuera opcional (con la importante diferencia de que si no marca cero, obtendrá un valor Error de tiempo de ejecución)

// Cannot be nil
var x: Int = 1

// The type here is not "Int", it's "Optional Int"
var y: Int? = 2

// The type here is "Implicitly Unwrapped Optional Int"
var z: Int! = 3

Uso:

// you can add x and z
x + z == 4

// ...but not x and y, because y needs to be unwrapped
x + y // error

// to add x and y you need to do:
x + y!

// but you *should* do this:
if let y_val = y {
    x + y_val
}
Jiaaro
fuente
7
Los opcionales implícitamente desenvueltos se describen en una sección con un nombre apropiado que comienza en la página 56 de El lenguaje de programación Swift .
Caleb
@Caleb He agregado un enlace a la sección relevante de los documentos en línea donde mencioné opciones opcionales implícitamente sin envolver :)
Jiaaro
Excelente información, gracias. En general, amar la seguridad que Swift nos está imponiendo hasta ahora debería producir muchos menos errores :).
Jason Renaldo
@Jiaaro: Muchas gracias por compartir. Hace que el usuario entienda perfectamente con el ejemplo anterior. !! :)
Esha
3
Creo que la frase " Este es básicamente el comportamiento que ya teníamos en el objetivo-c " puede resultar confusa. En Objective-C se puede acceder a un nilvalor y, de hecho el "trabajo" con él, en un rápido acceso a envolver implícitamente opcional, mientras que es nula será una excepción de tiempo de ejecución.
Sascha Wolf