Estoy aprendiendo Swift para iOS 8 / OSX 10.10 siguiendo este tutorial , y el término " valor sin envolver " se usa varias veces, como en este párrafo (en Objetos y clase ):
Cuando trabajas con valores opcionales, puedes escribir? antes de operaciones como métodos, propiedades y subíndice. Si el valor antes de la? es nulo, todo después del? se ignora y el valor de toda la expresión es nulo. De lo contrario, el valor opcional se desenvuelve y todo después de? actúa sobre el valor sin envolver . En ambos casos, el valor de toda la expresión es un valor opcional.
let optionalSquare: Square? = Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength
No lo entiendo, y busqué en la web sin suerte.
¿Qué significa esto?
Editar
De la respuesta de Cezary, hay una ligera diferencia entre la salida del código original y la solución final (probado en el patio de recreo):
Código original
La solución de Cezary
Las propiedades de la superclase se muestran en la salida en el segundo caso, mientras que hay un objeto vacío en el primer caso.
¿No se supone que el resultado sea idéntico en ambos casos?
Preguntas y respuestas relacionadas: ¿Qué es un valor opcional en Swift?
Respuestas:
Primero, debe comprender qué es un tipo Opcional. Un tipo opcional básicamente significa que la variable puede ser
nil
.Ejemplo:
El signo de interrogación indica el hecho de que
canBeNil
puede sernil
.Esto no funcionaría:
Para obtener el valor de su variable si es opcional, debe desenvolverlo . Esto solo significa poner un signo de exclamación al final.
Su código debería verse así:
Una nota al margen:
También puede declarar opciones opcionales para desenvolver automáticamente utilizando un signo de exclamación en lugar de un signo de interrogación.
Ejemplo:
Entonces, una forma alternativa de arreglar su código es:
EDITAR:
La diferencia que está viendo es exactamente el síntoma del hecho de que el valor opcional está envuelto . Hay otra capa encima. La versión sin envoltura solo muestra el objeto recto porque, bueno, está sin envolver.
Una comparación rápida de juegos:
En el primer y segundo casos, el objeto no se desenvuelve automáticamente, por lo que ve dos "capas" (
{{...}}
), mientras que en el tercer caso, solo ve una capa ({...}
) porque el objeto se desenvuelve automáticamente.La diferencia entre el primer caso y los segundos dos casos es que los segundos dos casos le darán un error de tiempo de ejecución si
optionalSquare
está configurado ennil
. Usando la sintaxis en el primer caso, puede hacer algo como esto:fuente
init()
función de la clase. Recomiendo leer los capítulos "Lo básico" (cubre opciones), "Inicialización" y "Encadenamiento opcional" en el libro de Swift publicado por Apple.La respuesta correcta existente es excelente, pero descubrí que para comprender esto completamente, necesitaba una buena analogía, ya que este es un concepto muy abstracto y extraño.
Entonces, permítanme ayudar a los demás desarrolladores de "cerebro derecho" (pensamiento visual) dándoles una perspectiva diferente además de la respuesta correcta. Aquí hay una buena analogía que me ayudó mucho.
Analogía de envoltura de regalo de cumpleaños
Piense en los opcionales como si fueran regalos de cumpleaños que vienen en envolturas rígidas, duras y de colores.
No sabes si hay algo dentro de la envoltura hasta que desenvuelves el presente, ¡tal vez no haya nada dentro! Si hay algo dentro, podría ser otro regalo más, que también está envuelto y que también puede no contener nada . Incluso podría desenvolver 100 regalos anidados para finalmente descubrir que no había nada más que envolver .
Si el valor de lo opcional no es
nil
, ahora ha revelado un cuadro que contiene algo . Pero, especialmente si el valor no se escribe explícitamente y es una variable y no una constante predefinida, entonces es posible que deba abrir el cuadro antes de poder saber algo específico sobre lo que hay en el cuadro, como qué tipo es o qué el valor real es¡¿Qué hay en la caja?! Analogía
Incluso después de desenvolver la variable, aún eres como Brad Pitt en la última escena en SE7EN ( advertencia : spoilers y lenguaje y violencia groseros con una calificación muy R), porque incluso después de desenvolver el presente, estás en la siguiente situación: ahora tienes
nil
, o una caja que contiene algo (pero no sabes qué).Puede que sepas el tipo de algo . Por ejemplo, si declara que la variable es tipo,
[Int:Any?]
entonces sabría que tiene un Diccionario (potencialmente vacío) con subíndices enteros que producen contenidos envueltos de cualquier tipo antiguo.Es por eso que tratar con tipos de colección (Diccionarios y matrices) en Swift puede ser un poco complicado.
Caso en punto:
fuente
Swift otorga una alta prima a la seguridad tipo. Todo el lenguaje Swift fue diseñado teniendo en cuenta la seguridad. Es uno de los sellos distintivos de Swift y uno que debes recibir con los brazos abiertos. Ayudará en el desarrollo de un código limpio y legible y ayudará a evitar que su aplicación se bloquee.
Todos los opcionales en Swift están demarcados con el
?
símbolo. Al establecer?
después del nombre del tipo en el que está declarando como opcional, esencialmente está convirtiendo esto no como el tipo que está antes del?
, sino como el tipo opcional .Usando opcional
Esto no significa que esté trabajando con un tipo de
String
. Esto significa que está trabajando con un tipo deString?
(Cadena opcional o Cadena opcional). De hecho, cada vez que intentasen tiempo de ejecución, se imprimirá la consola de depuración
Optional("foobar")
. La parte "Optional()
" indica que esta variable puede o no tener un valor en tiempo de ejecución, pero resulta que actualmente contiene la cadena "foobar". Esta "Optional()
" indicación permanecerá a menos que haga lo que se llama "desenvolver" el valor opcional.Desenvolver un opcional significa que ahora está convirtiendo ese tipo como no opcional. Esto generará un nuevo tipo y asignará el valor que residía dentro de ese opcional al nuevo tipo no opcional. De esta manera, puede realizar operaciones en esa variable, ya que el compilador garantiza que tiene un valor sólido.
Desenvolver condicionalmente verificará si el valor en el opcional es
nil
o no. Si no es asínil
, habrá una variable constante recién creada a la que se le asignará el valor y se desenvolverá en la constante no opcional. Y a partir de ahí, puede usar de forma segura lo no opcional en elif
bloque.La opción de desempaquetado condicional es la forma más limpia de acceder al valor de un opcional porque si contiene un valor nulo, todo lo que se encuentre dentro del bloque if let no se ejecutará. Por supuesto, como cualquier instrucción if, puede incluir un bloque else
El desenvolvimiento forzado se realiza empleando lo que se conoce como el
!
operador ("explosión"). Esto es menos seguro pero aún permite que su código se compile. Sin embargo, cada vez que use el operador de explosión, debe estar 1000% seguro de que su variable contiene un valor sólido antes de desenvolverse por la fuerza.Lo anterior es un código Swift completamente válido. Imprime el valor
myString
que se estableció como "foobar". El usuario lo veríafoobar
impreso en la consola y eso es todo. Pero supongamos que el valor nunca se estableció:Ahora tenemos una situación diferente en nuestras manos. A diferencia de Objective-C, cada vez que se intenta desenvolver por la fuerza un opcional, y el opcional no se ha configurado
nil
, es decir , cuando intenta desenvolver el opcional para ver qué hay dentro de su aplicación se bloqueará.Desenvoltura con fundición tipo . Como dijimos anteriormente, si bien usted es
unwrapping
el opcional, en realidad está convirtiendo a un tipo no opcional, también puede convertir el no opcional a un tipo diferente. Por ejemplo:En algún lugar de nuestro código, la variable
something
se establecerá con algún valor. Tal vez estamos usando genéricos o tal vez hay otra lógica que está causando que esto cambie. Entonces, más adelante en nuestro código, queremos usar,something
pero aún así podemos tratarlo de manera diferente si es un tipo diferente. En este caso, querrá usar laas
palabra clave para determinar esto:Observe la diferencia entre las dos
as
palabras clave. Como antes, cuando desenvolvimos a la fuerza un opcional, utilizamos el!
operador de explosión para hacerlo. Aquí harás lo mismo, pero en lugar de lanzarlo como no opcional, también lo lanzarás comoInt
. Y debe poder ser abatido ya queInt
, de lo contrario, es como usar el operador de explosión cuando el valor es quenil
su aplicación fallará.Y para utilizar estas variables en algún tipo de operación matemática, deben desenvolverse para hacerlo.
Por ejemplo, en Swift solo se pueden operar entre sí tipos de datos de números válidos del mismo tipo. Cuando emite un tipo con el
as!
, está forzando el rechazo de esa variable como si estuviera seguro de que es de ese tipo, por lo tanto, es seguro operar y no bloquear su aplicación. Esto está bien siempre y cuando la variable sea del tipo al que la estás enviando, de lo contrario tendrás un desastre en tus manos.Sin embargo, la transmisión con
as!
permitirá que su código se compile. Al lanzar con unas?
es una historia diferente. De hecho,as?
declara suInt
como un tipo de datos completamente diferente todos juntos.Ahora es
Optional(0)
Y si alguna vez trataste de hacer tu tarea escribiendo algo como
Es probable que tu profesor de matemáticas te haya dado una "F". Lo mismo con Swift. Excepto que Swift preferiría no compilar en absoluto en lugar de darle una calificación. Porque al final del día, lo opcional puede ser nulo .
Safety First Kids.
fuente
'?' significa expresión de encadenamiento opcional,
el '!' significa fuerza-valor
fuente