De la documentación de Apple :
Puede usar
if
ylet
juntos para trabajar con valores que pueden faltar. Estos valores se representan como opcionales. Un valor opcional contiene un valor o contienenil
para indicar que falta el valor. Escriba un signo de interrogación (?
) después del tipo de un valor para marcar el valor como opcional.
¿Por qué querrías usar un valor opcional?
Respuestas:
Un opcional en Swift es un tipo que puede contener un valor o ningún valor. Los opcionales se escriben agregando a
?
a cualquier tipo:Los opcionales (junto con los genéricos) son uno de los conceptos Swift más difíciles de entender. Debido a cómo se escriben y usan, es fácil hacerse una idea equivocada de lo que son. Compare la opción anterior para crear una cadena normal:
Desde la sintaxis, parece que una Cadena opcional es muy similar a una Cadena ordinaria. No es. Una cadena opcional no es una cadena con alguna configuración "opcional" activada. No es una variedad especial de String. Una cadena y una cadena opcional son tipos completamente diferentes.
Esto es lo más importante que debes saber: un opcional es un tipo de contenedor. Una cadena opcional es un contenedor que puede contener una cadena. Un Int opcional es un contenedor que puede contener un Int. Piense en un opcional como una especie de paquete. Antes de abrirlo (o "desenvolverlo" en el idioma de los opcionales) no sabrá si contiene algo o nada.
Puede ver cómo se implementan los opcionales en la Biblioteca estándar de Swift escribiendo "Opcional" en cualquier archivo Swift y haciendo clic en él. Aquí está la parte importante de la definición:
Opcional es solo uno
enum
que puede ser uno de dos casos:.none
o.some
. Si es así.some
, hay un valor asociado que, en el ejemplo anterior, sería elString
"Hola". Un opcional usa Generics para dar un tipo al valor asociado. El tipo de una cadena opcional no esString
, esOptional
, o más precisamenteOptional<String>
.Todo lo que Swift hace con las opciones es mágico para que el código de lectura y escritura sea más fluido. Desafortunadamente, esto oscurece la forma en que realmente funciona. Revisaré algunos de los trucos más tarde.
Nota: Hablaré mucho sobre variables opcionales, pero también está bien crear constantes opcionales. Marco todas las variables con su tipo para facilitar la comprensión de los tipos de tipos que se crean, pero no es necesario que lo haga en su propio código.
Cómo crear opcionales
Para crear un opcional, agregue un
?
después del tipo que desea ajustar. Cualquier tipo puede ser opcional, incluso sus propios tipos personalizados. No puede haber un espacio entre el tipo y el?
.Usando opcionales
Puede comparar un opcional
nil
para ver si tiene un valor:Esto es un poco confuso. Implica que un opcional es una cosa u otra. Es nulo o es "Bob". Esto no es cierto, lo opcional no se transforma en otra cosa. Compararlo con cero es un truco para hacer que el código sea más fácil de leer. Si un opcional es igual a cero, esto solo significa que la enumeración está configurada actualmente en
.none
.Solo los opcionales pueden ser nulos
Si intenta establecer una variable no opcional en nula, obtendrá un error.
Otra forma de ver las opciones es como complemento de las variables normales de Swift. Son una contraparte de una variable que tiene un valor garantizado. Swift es un lenguaje cuidadoso que odia la ambigüedad. La mayoría de las variables se definen como no opcionales, pero a veces esto no es posible. Por ejemplo, imagine un controlador de vista que carga una imagen desde un caché o desde la red. Puede o no tener esa imagen en el momento en que se crea el controlador de vista. No hay forma de garantizar el valor de la variable de imagen. En este caso, deberías hacerlo opcional. Comienza como
nil
y cuando se recupera la imagen, lo opcional obtiene un valor.El uso de un opcional revela la intención de los programadores. En comparación con Objective-C, donde cualquier objeto podría ser nulo, Swift necesita que tenga claro cuándo puede faltar un valor y cuándo se garantiza que exista.
Para usar un opcional, lo "desenvuelves"
Un opcional
String
no se puede utilizar en lugar de un realString
. Para usar el valor envuelto dentro de un opcional, debe desenvolverlo. La forma más sencilla de desenvolver un opcional es agregar un!
después del nombre opcional. Esto se llama "desenvolvimiento forzado". Devuelve el valor dentro del opcional (como el tipo original) pero si el opcional esnil
, provoca un bloqueo en tiempo de ejecución. Antes de desenvolver, debe asegurarse de que haya un valor.Comprobación y uso de un opcional
Debido a que siempre debe verificar cero antes de desenvolver y usar un opcional, este es un patrón común:
En este patrón, verifica que hay un valor presente, luego, cuando está seguro de que lo está, fuerza a desenvolverlo en una constante temporal para usar. Debido a que esto es algo muy común, Swift ofrece un acceso directo usando "if let". Esto se llama "enlace opcional".
Esto crea una constante temporal (o variable si la reemplaza
let
convar
) cuyo alcance solo está dentro de las llaves del if. Debido a que tener que usar un nombre como "unwrappedMealPreference" o "realMealPreference" es una carga, Swift le permite reutilizar el nombre de la variable original, creando uno temporal dentro del alcance del paréntesisAquí hay un código para demostrar que se usa una variable diferente:
El enlace opcional funciona comprobando si el opcional es igual a cero. Si no lo hace, desenvuelve lo opcional en la constante proporcionada y ejecuta el bloque. En Xcode 8.3 y versiones posteriores (Swift 3.1), intentar imprimir una opción como esta provocará una advertencia inútil. Usa los opcionales
debugDescription
para silenciarlo:¿Para qué son opcionales?
Los opcionales tienen dos casos de uso:
Algunos ejemplos concretos:
middleName
ospouse
en unaPerson
claseweak
propiedades en clases. Lo que señalan se puede configurarnil
en cualquier momentoBoolean
Las opciones no existen en Objective-C pero hay un concepto equivalente, que devuelve nil. Los métodos que pueden devolver un objeto pueden devolver nil en su lugar. Esto se toma como "la ausencia de un objeto válido" y a menudo se usa para decir que algo salió mal. Solo funciona con objetos Objective-C, no con primitivas o tipos C básicos (enumeraciones, estructuras). Objective-C a menudo se había especializado tipos para representar la ausencia de estos valores (
NSNotFound
que en realidad esNSIntegerMax
,kCLLocationCoordinate2DInvalid
para representar un inválido de coordenadas,-1
o también se utilizan algún valor negativo). El codificador debe conocer estos valores especiales, por lo que deben documentarse y aprenderse para cada caso. Si un método no puede tomarsenil
como parámetro, esto debe documentarse. En el objetivo-C,nil
era un puntero al igual que todos los objetos se definían como punteros, peronil
apuntaban a una dirección específica (cero). En Swift,nil
es un literal que significa la ausencia de cierto tipo.Comparado a
nil
Solía poder usar cualquier opcional como
Boolean
:En las versiones más recientes de Swift tienes que usar
leatherTrim != nil
. ¿Por qué es esto? El problema es que unBoolean
puede ser envuelto en un opcional. Si tienesBoolean
así:tiene dos tipos de "falso", uno donde no hay valor y otro donde tiene un valor pero el valor es
false
. Swift odia la ambigüedad, por lo que ahora siempre debe verificar una opción opcionalnil
.¿Te preguntarás cuál es el objetivo de un opcional
Boolean
? Al igual que con otras opciones, el.none
estado podría indicar que el valor aún se desconoce. Puede haber algo en el otro extremo de una llamada de red que demore un poco en sondear. Los booleanos opcionales también se denominan " booleanos de tres valores "Trucos rápidos
Swift utiliza algunos trucos para permitir que funcionen los opcionales. Considere estas tres líneas de código opcional de aspecto ordinario;
Ninguna de estas líneas debe compilarse.
String
tipo diferenteRevisaré algunos de los detalles de implementación de las opciones que permiten que estas líneas funcionen.
Crear un opcional
El uso
?
para crear un opcional es azúcar sintáctico, habilitado por el compilador Swift. Si desea hacerlo a lo largo, puede crear una opción como esta:Esto llama
Optional
al primer inicializador,public init(_ some: Wrapped)
que infiere el tipo asociado del opcional del tipo utilizado entre paréntesis.La forma aún más larga de crear y configurar un opcional:
Establecer un opcional para
nil
Puede crear un opcional sin valor inicial, o crear uno con el valor inicial de
nil
(ambos tienen el mismo resultado).Permitir que los opcionales sean iguales
nil
está habilitado por el protocoloExpressibleByNilLiteral
(anteriormente nombradoNilLiteralConvertible
). La opción se crea conOptional
la segunda inicializador 's,public init(nilLiteral: ())
. Los documentos dicen que no debes usarExpressibleByNilLiteral
para nada excepto los opcionales, ya que eso cambiaría el significado de nulo en tu código, pero es posible hacerlo:El mismo protocolo le permite configurar un opcional ya creado para
nil
. Aunque no se recomienda, puede usar el inicializador literal nulo directamente:Comparando un opcional a
nil
Los opcionales definen dos operadores especiales "==" y "! =", Que puede ver en la
Optional
definición. La primera le==
permite verificar si alguna opción es igual a cero. Dos opciones diferentes que se establecen en .none siempre serán iguales si los tipos asociados son los mismos. Cuando compara con cero, detrás de escena Swift crea un opcional del mismo tipo asociado, establecido en .none y luego lo usa para la comparación.El segundo
==
operador le permite comparar dos opciones. Ambos tienen que ser del mismo tipo y ese tipo debe ajustarseEquatable
(el protocolo que permite comparar cosas con el operador "==" normal). Swift (presumiblemente) desenvuelve los dos valores y los compara directamente. También maneja el caso donde uno o ambos de los opcionales son.none
. Tenga en cuenta la distinción entre comparar con elnil
literal.Además, le permite comparar cualquier
Equatable
tipo con una envoltura opcional de ese tipo:Detrás de escena, Swift envuelve lo no opcional como opcional antes de la comparación. Funciona también con literales (
if 23 == numberFromString {
)Dije que hay dos
==
operadores, pero en realidad hay un tercero que le permite colocarnil
el lado izquierdo de la comparación.Nombramientos opcionales
No existe una convención Swift para nombrar tipos opcionales de manera diferente a los tipos no opcionales. Las personas evitan agregar algo al nombre para mostrar que es opcional (como "optionalMiddleName" o "possibleNumberAsString") y dejan que la declaración muestre que es un tipo opcional. Esto se vuelve difícil cuando quieres nombrar algo para mantener el valor de un opcional. El nombre "middleName" implica que es un tipo String, por lo que cuando extrae el valor String de él, a menudo puede terminar con nombres como "actualMiddleName" o "unwrappedMiddleName" o "realMiddleName". Utilice el enlace opcional y reutilice el nombre de la variable para evitar esto.
La definición oficial
De "The Basics" en el lenguaje de programación Swift :
Para terminar, aquí hay un poema de 1899 sobre opciones:
Ayer, en la escalera
, conocí a un hombre que no estaba allí.
No estaba allí otra vez hoy
. Deseo, deseo que se vaya
Antigonish.
Más recursos:
fuente
if myString
ya no se compila. Es necesarioif myString != nil
. Ver documentación .Tomemos el ejemplo de un
NSError
, si no se devuelve un error, desearía que sea opcional devolver Nil. No tiene sentido asignarle un valor si no hay un error.Esto también le permite tener un valor predeterminado. Por lo tanto, puede establecer un método con un valor predeterminado si la función no pasa nada
fuente
func isNil<T>(t: T?) -> Bool { return t == nil }
regresarátrue
incluso si hay un valor opcional que estánil
en la expresión.return x == 5
? ¿Qué tiene de especial el 5?No puede tener una variable que apunte
nil
en Swift: no hay punteros ni punteros nulos. Pero en una API, a menudo desea poder indicar un tipo específico de valor o una falta de valor, por ejemplo, ¿mi ventana tiene un delegado? De ser así, ¿quién es? Los opcionales son la forma segura de escribir y segura de Swift para hacer esto.fuente
Hice una respuesta corta, que resume la mayor parte de lo anterior, para limpiar la incertidumbre que tenía en mi cabeza como principiante:
Opuesto a Objective-C, ninguna variable puede contener nil en Swift, por lo que se agregó el tipo de variable Opcional (variables con sufijo "?"):
La gran diferencia es que las variables opcionales no almacenan valores directamente (como lo harían las variables Obj-C normales), contienen dos estados : " tiene un valor " o " tiene cero ":
Es decir, puede verificar esas variables en diferentes situaciones:
Al usar el "!" sufijo, también puede acceder a los valores envueltos en ellos, solo si existen . (es decir, no es nulo ):
Es por eso que necesitas usar "?" y "!" y no usarlos todos por defecto. (este fue mi mayor desconcierto)
También estoy de acuerdo con la respuesta anterior: el tipo opcional no se puede usar como booleano .
fuente
En el objetivo C, las variables sin valor eran iguales a 'nulo' (también era posible usar valores 'nulo' igual a 0 y falso), por lo tanto, era posible usar variables en declaraciones condicionales (las variables que tienen valores son iguales a 'VERDADERO' 'y aquellos sin valores eran iguales a' FALSO ').
Swift proporciona seguridad de tipo al proporcionar 'valor opcional'. es decir, evita errores formados al asignar variables de diferentes tipos.
Entonces, en Swift, solo se pueden proporcionar booleanos en las declaraciones condicionales.
Aquí, aunque 'hw' es una cadena, no se puede usar en una declaración if como en el objetivo C.
Para eso necesita ser creado como,
fuente
El valor opcional le permite mostrar la ausencia de valor. Un poco como NULL en SQL o NSNull en Objective-C. Supongo que esto será una mejora, ya que puedes usarlo incluso para tipos "primitivos".
Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks https://itun.es/gb/jEUH0.l
fuente
nil
es solo azúcar sintáctico para la constante enumOptionalValue<T>.None
(dondeT
es el tipo apropiado para el contexto donde está usandonil
).?
es un acceso directo paraOptionalValue<T>.Some(T)
.Una opción significa que Swift no está completamente seguro si el valor corresponde al tipo: por ejemplo, Int? significa que Swift no está completamente seguro de si el número es un Int.
1) Si está absolutamente seguro del tipo, puede usar un signo de exclamación para forzar el desenvolvimiento, así:
Si fuerza desenvolver un opcional y es igual a cero, puede encontrar este error de bloqueo:
Esto no es necesariamente seguro, por lo que aquí hay un método que podría evitar fallas en caso de que no esté seguro del tipo y el valor:
2) La opción implícitamente desenvuelta
3) La declaración de guardia
Desde aquí, puede seguir adelante y usar la variable sin envolver. Asegúrese de forzar el desenvolvimiento (con un!), Si está seguro del tipo de variable.
fuente
Cuando comencé a aprender
Swift
fue muy difícil darse cuenta de por qué opcional .Pensemos de esta manera. Consideremos una clase
Person
que tiene dos propiedadesname
ycompany
.Ahora creemos pocos objetos de
Person
Pero no podemos pasar
Nil
aname
Ahora hablemos de por qué lo usamos
optional?
. Consideremos una situación en la que queremos agregarInc
después del nombre de la compañía comoapple
seráapple Inc
. Necesitamos agregarInc
después del nombre de la empresa e imprimir.Ahora estudiemos por qué lo opcional tiene lugar.
Vamos a reemplazar
bob
contom
Y felicidades! hemos tratado adecuadamente
optional?
Entonces los puntos de realización son
nil
nil
.Gracias ... feliz codificación
fuente
Experimentemos con el siguiente código Playground . Espero tener una idea clara de lo que es opcional y la razón de usarlo.
fuente
De https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :
Para entender más profundamente, lea el enlace de arriba.
fuente
Bien...
La principal diferencia es que el encadenamiento opcional falla correctamente cuando el opcional es nulo, mientras que el desenvolvimiento forzado desencadena un error de tiempo de ejecución cuando el opcional es nulo.
Para reflejar el hecho de que se puede invocar el encadenamiento opcional en un valor nulo, el resultado de una llamada de encadenamiento opcional siempre es un valor opcional, incluso si la propiedad, el método o el subíndice que está consultando devuelve un valor no opcional. Puede usar este valor de retorno opcional para verificar si la llamada de encadenamiento opcional fue exitosa (el opcional devuelto contiene un valor) o si no tuvo éxito debido a un valor nulo en la cadena (el valor opcional devuelto es nulo).
Específicamente, el resultado de una llamada de encadenamiento opcional es del mismo tipo que el valor de retorno esperado, pero envuelto en un opcional. ¿Una propiedad que normalmente devuelve un Int devolverá un Int? cuando se accede mediante encadenamiento opcional.
Aquí hay un tutorial básico en detalle, por el Comité de Desarrolladores de Apple: Encadenamiento opcional
fuente
Un opcional en Swift es un tipo que puede contener un valor o ningún valor. Los opcionales se escriben agregando un ? a cualquier tipo:
Puede consultar este enlace para obtener conocimiento en profundidad: https://medium.com/@agoiabeladeyemi/optionals-in-swift-2b141f12f870
fuente
Aquí hay una declaración opcional equivalente en Swift:
Esta declaración crea una variable llamada middleName de tipo String. El signo de interrogación (?) Después del tipo de variable String indica que la variable middleName puede contener un valor que puede ser String o nil. Cualquiera que vea este código inmediatamente sabe que middleName puede ser nulo. ¡Es autodocumentado!
Si no especifica un valor inicial para una constante o variable opcional (como se muestra arriba), el valor se establece automáticamente en cero para usted. Si lo prefiere, puede establecer explícitamente el valor inicial en nil:
para más detalles para leer opcionalmente debajo del enlace
http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values
fuente