¿Qué es un valor opcional en Swift?


267

De la documentación de Apple :

Puede usar ify letjuntos para trabajar con valores que pueden faltar. Estos valores se representan como opcionales. Un valor opcional contiene un valor o contiene nilpara 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?



1
Opcional también se puede ver como una implementación de la opción / tal vez mónada . Este blog aquí hace un buen trabajo al tratar de explicar lo que de otro modo sería un concepto difícil.
StuartLC

tldr: "Swift necesita que tengas claro cuándo puede faltar un valor y cuándo se garantiza que exista". de la excelente respuesta
jonatan

Respuestas:


532

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:

var name: String? = "Bertie"

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:

var name: String = "Bertie" // No "?" after String

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:

enum Optional<Wrapped> {
    case none
    case some(Wrapped)
}

Opcional es solo uno enumque puede ser uno de dos casos: .noneo .some. Si es así .some, hay un valor asociado que, en el ejemplo anterior, sería el String"Hola". Un opcional usa Generics para dar un tipo al valor asociado. El tipo de una cadena opcional no es String, es Optional, o más precisamente Optional<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 ?.

var name: String? = "Bob" // Create an optional String that contains "Bob"
var peter: Person? = Person() // An optional "Person" (custom type)

// A class with a String and an optional String property
class Car {
var modelName: String // must exist
var internalName: String? // may or may not exist
}

Usando opcionales

Puede comparar un opcional nilpara ver si tiene un valor:

var name: String? = "Bob"
name = nil // Set name to nil, the absence of a value
if name != nil {
    print("There is a name")
}
if name == nil { // Could also use an "else"
    print("Name has no value")
}

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.

var red: String = "Red"
red = nil // error: nil cannot be assigned to type 'String'

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 comonil 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 Stringno se puede utilizar en lugar de un real String. 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 es nil, provoca un bloqueo en tiempo de ejecución. Antes de desenvolver, debe asegurarse de que haya un valor.

var name: String? = "Bob"
let unwrappedName: String = name!
print("Unwrapped name: \(unwrappedName)")

name = nil
let nilName: String = name! // Runtime crash. Unexpected nil.

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:

var mealPreference: String? = "Vegetarian"
if mealPreference != nil {
    let unwrappedMealPreference: String = mealPreference!
    print("Meal: \(unwrappedMealPreference)") // or do something useful
}

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".

var mealPreference: String? = "Vegetarian"
if let unwrappedMealPreference: String = mealPreference {
    print("Meal: \(unwrappedMealPreference)") 
}

Esto crea una constante temporal (o variable si la reemplaza letcon var) 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éntesis

var mealPreference: String? = "Vegetarian"
if let mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // separate from the other mealPreference
}

Aquí hay un código para demostrar que se usa una variable diferente:

var mealPreference: String? = "Vegetarian"
if var mealPreference: String = mealPreference {
    print("Meal: \(mealPreference)") // mealPreference is a String, not a String?
    mealPreference = "Beef" // No effect on original
}
// This is the original mealPreference
print("Meal: \(mealPreference)") // Prints "Meal: Optional("Vegetarian")"

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 debugDescriptionpara silenciarlo:

print("\(mealPreference.debugDescription)")

¿Para qué son opcionales?

Los opcionales tienen dos casos de uso:

  1. Cosas que pueden fallar (esperaba algo pero no obtuve nada)
  2. Cosas que ahora no son nada pero que podrían ser algo más tarde (y viceversa)

Algunos ejemplos concretos:

  • Una propiedad que puede estar allí o no, como middleNameo spouseen una Personclase
  • Un método que puede devolver un valor o nada, como buscar una coincidencia en una matriz
  • Un método que puede devolver un resultado u obtener un error y no devolver nada, como intentar leer el contenido de un archivo (que normalmente devuelve los datos del archivo) pero el archivo no existe
  • Delegar propiedades, que no siempre tienen que establecerse y generalmente se establecen después de la inicialización
  • Para weakpropiedades en clases. Lo que señalan se puede configurar nilen cualquier momento
  • Un gran recurso que podría tener que liberarse para recuperar memoria
  • Cuando necesita una forma de saber cuándo se ha establecido un valor (datos aún no cargados> los datos) en lugar de usar un dataLoaded separado Boolean

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 ( NSNotFoundque en realidad es NSIntegerMax, kCLLocationCoordinate2DInvalidpara representar un inválido de coordenadas, -1o 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 tomarse nilcomo parámetro, esto debe documentarse. En el objetivo-C,nilera un puntero al igual que todos los objetos se definían como punteros, pero nilapuntaban a una dirección específica (cero). En Swift, niles un literal que significa la ausencia de cierto tipo.


Comparado a nil

Solía ​​poder usar cualquier opcional como Boolean:

let leatherTrim: CarExtras? = nil
if leatherTrim {
    price = price + 1000
}

En las versiones más recientes de Swift tienes que usar leatherTrim != nil. ¿Por qué es esto? El problema es que un Booleanpuede ser envuelto en un opcional. Si tienes Booleanasí:

var ambiguous: Boolean? = false

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 opcional nil.

¿Te preguntarás cuál es el objetivo de un opcional Boolean? Al igual que con otras opciones, el .noneestado 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;

var religiousAffiliation: String? = "Rastafarian"
religiousAffiliation = nil
if religiousAffiliation != nil { ... }

Ninguna de estas líneas debe compilarse.

  • La primera línea establece una cadena opcional utilizando un literal de cadena, dos tipos diferentes. Incluso si esto fuera un Stringtipo diferente
  • La segunda línea establece una cadena opcional en cero, dos tipos diferentes
  • La tercera línea compara una cadena opcional con cero, dos tipos diferentes

Revisaré 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:

var name: Optional<String> = Optional("Bob")

Esto llama Optionalal 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:

var serialNumber:String? = Optional.none
serialNumber = Optional.some("1234")
print("\(serialNumber.debugDescription)")

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).

var name: String?
var name: String? = nil

Permitir que los opcionales sean iguales nilestá habilitado por el protocolo ExpressibleByNilLiteral(anteriormente nombrado NilLiteralConvertible). La opción se crea con Optionalla segunda inicializador 's, public init(nilLiteral: ()). Los documentos dicen que no debes usar ExpressibleByNilLiteralpara nada excepto los opcionales, ya que eso cambiaría el significado de nulo en tu código, pero es posible hacerlo:

class Clint: ExpressibleByNilLiteral {
    var name: String?
    required init(nilLiteral: ()) {
        name = "The Man with No Name"
    }
}

let clint: Clint = nil // Would normally give an error
print("\(clint.name)")

El mismo protocolo le permite configurar un opcional ya creado para nil. Aunque no se recomienda, puede usar el inicializador literal nulo directamente:

var name: Optional<String> = Optional(nilLiteral: ())

Comparando un opcional a nil

Los opcionales definen dos operadores especiales "==" y "! =", Que puede ver en la Optionaldefinició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.

// How Swift actually compares to nil
var tuxedoRequired: String? = nil
let temp: Optional<String> = Optional.none
if tuxedoRequired == temp { // equivalent to if tuxedoRequired == nil
    print("tuxedoRequired is nil")
}

El segundo ==operador le permite comparar dos opciones. Ambos tienen que ser del mismo tipo y ese tipo debe ajustarse Equatable(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 el nilliteral.

Además, le permite comparar cualquier Equatabletipo con una envoltura opcional de ese tipo:

let numberToFind: Int = 23
let numberFromString: Int? = Int("23") // Optional(23)
if numberToFind == numberFromString {
    print("It's a match!") // Prints "It's a match!"
}

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 colocar nilel lado izquierdo de la comparación.

if nil == name { ... }

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 :

Swift también introduce tipos opcionales, que manejan la ausencia de un valor. Los opcionales dicen "hay un valor y es igual a x" o "no hay ningún valor". Las opciones son similares a usar nil con punteros en Objective-C, pero funcionan para cualquier tipo, no solo para clases. Los opcionales son más seguros y expresivos que los punteros nulos en Objective-C y están en el corazón de muchas de las características más poderosas de Swift.

Los opcionales son un ejemplo del hecho de que Swift es un lenguaje de tipo seguro. Swift lo ayuda a ser claro acerca de los tipos de valores con los que puede trabajar su código. Si parte de su código espera una Cadena, el tipo de seguridad le impide pasar un Int por error. Esto le permite detectar y corregir errores lo antes posible en el proceso de desarrollo.


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:


55
@KaanDedeoglu Desafortunadamente, Steve es muy opcional. Estaba aquí y ahora no.
nevan king

19
if myStringya no se compila. Es necesario if myString != nil. Ver documentación .
Pang

55
¿La mejor y más clara explicación para? y! uso en Swift que encontré en la web. gracias
mindbomb

2
mateo explica en profundidad los opcionales, llegando en profundidad y ejemplos fáciles.
iluvatar_GR

44
Gracias por esta explicación, es mucho más clara que la documentación de Apple.
yesthisisjoe

16

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.

var error: NSError? = nil

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

func doesntEnterNumber(x: Int? = 5) -> Bool {
    if (x == 5){
        return true
    } else {
        return false
    }
}

La oración "Si es nula, el resultado de cualquier expresión con ella también es nula" es simplemente incorrecta. func isNil<T>(t: T?) -> Bool { return t == nil }regresará trueincluso si hay un valor opcional que está nilen la expresión.
Vuelve el verdadero

Ejemplo de código increíblemente malo. ¿No podrías pensar en algo mejor? ¿Por qué no simplemente?return x == 5 ? ¿Qué tiene de especial el 5?
Atomosk

No, hace 2 años no podía pensar en algo mejor. Hoy sí, pero ¿se entiende esto? si. Gracias por la entrada @Atomosk, es realmente útil.
John Riselvato

12

No puede tener una variable que apunte nilen 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.


11

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 "?"):

    var aString = nil //error

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 ":

    var aString: String? = "Hello, World!"
    aString = nil //correct, now it contains the state "has nil"

Es decir, puede verificar esas variables en diferentes situaciones:

if let myString = aString? {
     println(myString)
}
else { 
     println("It's nil") // this will print in our case
}

Al usar el "!" sufijo, también puede acceder a los valores envueltos en ellos, solo si existen . (es decir, no es nulo ):

let aString: String? = "Hello, World!"
// var anotherString: String = aString //error
var anotherString: String = aString!

println(anotherString) //it will print "Hello, World!"

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 .


7

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.

var hw = "Hello World"

Aquí, aunque 'hw' es una cadena, no se puede usar en una declaración if como en el objetivo C.

//This is an error

if hw

 {..}

Para eso necesita ser creado como,

var nhw : String? = "Hello World"

//This is correct

if nhw

 {..}

5

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".

// Reimplement the Swift standard library's optional type
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)

Extracto de: Apple Inc. "El lenguaje de programación Swift". iBooks https://itun.es/gb/jEUH0.l


66
niles solo azúcar sintáctico para la constante enum OptionalValue<T>.None(donde Tes el tipo apropiado para el contexto donde está usando nil). ?es un acceso directo para OptionalValue<T>.Some(T).
rickster

4

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.

Para eliminarlo, hay tres métodos que puede emplear.

1) Si está absolutamente seguro del tipo, puede usar un signo de exclamación para forzar el desenvolvimiento, así:

// Here is an optional variable:

var age: Int?

// Here is how you would force unwrap it:

var unwrappedAge = age!

Si fuerza desenvolver un opcional y es igual a cero, puede encontrar este error de bloqueo:

ingrese la descripción de la imagen aquí

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:

Los métodos 2 y tres protegen contra este problema.

2) La opción implícitamente desenvuelta

 if let unwrappedAge = age {

 // continue in here

 }

Tenga en cuenta que el tipo sin envolver ahora es Int , en lugar de Int? .

3) La declaración de guardia

 guard let unwrappedAge = age else { 
   // continue in here
 }

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.

¡Buena suerte con tu proyecto!


1

Cuando comencé a aprender Swiftfue muy difícil darse cuenta de por qué opcional .

Pensemos de esta manera. Consideremos una clase Personque tiene dos propiedades namey company.

class Person: NSObject {

    var name : String //Person must have a value so its no marked as optional
    var companyName : String? ///Company is optional as a person can be unemployed that is nil value is possible

    init(name:String,company:String?) {

        self.name = name
        self.companyName = company

    }
}

Ahora creemos pocos objetos de Person

var tom:Person = Person.init(name: "Tom", company: "Apple")//posible
var bob:Person = Person.init(name: "Bob", company:nil) // also Possible because company is marked as optional so we can give Nil

Pero no podemos pasar Nilaname

var personWithNoName:Person = Person.init(name: nil, company: nil)

Ahora hablemos de por qué lo usamos optional?. Consideremos una situación en la que queremos agregar Incdespués del nombre de la compañía como appleserá apple Inc. Necesitamos agregar Incdespués del nombre de la empresa e imprimir.

print(tom.companyName+" Inc") ///Error saying optional is not unwrapped.
print(tom.companyName!+" Inc") ///Error Gone..we have forcefully unwrap it which is wrong approach..Will look in Next line
print(bob.companyName!+" Inc") ///Crash!!!because bob has no company and nil can be unwrapped.

Ahora estudiemos por qué lo opcional tiene lugar.

if let companyString:String = bob.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Vamos a reemplazar bobcontom

if let companyString:String = tom.companyName{///Compiler safely unwrap company if not nil.If nil,no unwrap.

    print(companyString+" Inc") //Will never executed and no crash!!!
}

Y felicidades! hemos tratado adecuadamenteoptional?

Entonces los puntos de realización son

  1. Marcaremos una variable como opcional si es posible que sea nil
  2. Si queremos usar esta variable en algún lugar del compilador de código, le recordaremos que debemos verificar si tenemos un trato adecuado con esa variable si contiene nil.

Gracias ... feliz codificación


0

Experimentemos con el siguiente código Playground . Espero tener una idea clara de lo que es opcional y la razón de usarlo.

var sampleString: String? ///Optional, Possible to be nil

sampleString = nil ////perfactly valid as its optional

sampleString = "some value"  //Will hold the value

if let value = sampleString{ /// the sampleString is placed into value with auto force upwraped.

    print(value+value)  ////Sample String merged into Two
}

sampleString = nil // value is nil and the

if let value = sampleString{

    print(value + value)  ///Will Not execute and safe for nil checking
}

//   print(sampleString! + sampleString!)  //this line Will crash as + operator can not add nil

0

De https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/OptionalChaining.html :

El encadenamiento opcional es un proceso para consultar y llamar a propiedades, métodos y subíndices en un opcional que actualmente puede ser nulo. Si el opcional contiene un valor, la propiedad, el método o la llamada de subíndice se realiza correctamente; si el opcional es nil, la propiedad, el método o la llamada de subíndice devuelve nil. Se pueden encadenar varias consultas juntas, y la cadena completa falla correctamente si algún enlace en la cadena es nulo.

Para entender más profundamente, lea el enlace de arriba.


0

Bien...

? (Opcional) indica que su variable puede contener un valor nulo mientras ! (desempaquetado) indica que su variable debe tener una memoria (o valor) cuando se usa (intentó obtener un valor) en tiempo de ejecución.

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.

var defaultNil : Int?  // declared variable with default nil value
println(defaultNil) >> nil  

var canBeNil : Int? = 4
println(canBeNil) >> optional(4)

canBeNil = nil
println(canBeNil) >> nil

println(canBeNil!) >> // Here nil optional variable is being unwrapped using ! mark (symbol), that will show runtime error. Because a nil optional is being tried to get value using unwrapper

var canNotBeNil : Int! = 4
print(canNotBeNil) >> 4

var cantBeNil : Int = 4
cantBeNil = nil // can't do this as it's not optional and show a compile time error

Aquí hay un tutorial básico en detalle, por el Comité de Desarrolladores de Apple: Encadenamiento opcional



-1

Aquí hay una declaración opcional equivalente en Swift:

var middleName: String?

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:

var middleName: String? = nil

para más detalles para leer opcionalmente debajo del enlace

http://www.iphonelife.com/blog/31369/swift-101-working-swifts-new-optional-values


use esto, var middleName: String! = ""
Gaurav
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.