Dado lo siguiente en Swift:
var optionalString: String?
let dict = NSDictionary()
¿Cuál es la diferencia práctica entre las siguientes dos declaraciones:
optionalString = dict.objectForKey("SomeKey") as? String
vs
optionalString = dict.objectForKey("SomeKey") as! String?
swift
optional
downcast
optional-variables
sdduursma
fuente
fuente
Respuestas:
La diferencia práctica es esta:
optionalString
será una variable de tipoString?
. Si el tipo subyacente es diferente aString
esto, esto se asignará sin causar dañonil
al opcional.Esto dice, sé que esto es un
String?
. Esto también resultará enoptionalString
ser de tipoString?
, pero fallará si el tipo subyacente es otro.El primer estilo se usa luego con
if let
para desenvolver de manera segura el opcional:fuente
as? Types
- significa que el proceso de fundición hacia abajo es opcional. El proceso puede ser exitoso o no (el sistema devolverá nil si falla el down casting). De ninguna manera fallará si falla el down casting.as! Type?
- Aquí el proceso de down casting debería ser exitoso (!
indica que). El signo de interrogación final indica si el resultado final puede ser nulo o no.Más información sobre "!" y "?"
Tomemos 2 casos
Considerar:
Aquí no sabemos si el resultado de la conversión descendente de la celda con el identificador "Celda" a UITableViewCell es un éxito o no. Si no tiene éxito, devuelve nil (por lo que evitamos el bloqueo aquí). Aquí podemos hacer lo que se indica a continuación.
Así que recordémoslo así: si
?
eso significa que no estamos seguros de si el valor es nulo o no (el signo de interrogación aparece cuando no sabemos cosas).Contraste eso con:
Aquí le decimos al compilador que la conversión descendente debería ser exitosa. Si falla, el sistema se bloqueará. Entonces damos
!
cuando estamos seguros de que el valor no es nulo.fuente
Para aclarar lo que dijo vacawama, aquí hay un ejemplo ...
Swift 3.0:
Swift 2.0:
fuente
intNil as! String? // ==nil
no causa un bloqueo !!! ???, como <Int> opcional. Ninguno es diferente de <String> opcionalas?
aString
? ¿Por qué no lo abatisteString?
? ¿Por qué no abatidoas!
aString
?Any
lugar deAnyObject
as
utilizado para upcasting y tipo casting a tipo puenteas?
utilizado para fundición segura, devuelve cero si fallaas!
utilizado para forzar el lanzamiento, se bloquea si fallaNota:
as!
no se puede convertir el tipo sin formato a opcionalEjemplos:
Ejemplo
Añadiendo un ?inmediatamente después del tipo de datos, le dice al compilador que la variable puede contener un número o no. ¡Ordenado! Tenga en cuenta que realmente no tiene sentido definir las constantes opcionales: puede establecer su valor solo una vez y, por lo tanto, podría decir si su valor será nulo o no.
¿Cuándo deberíamos usar "?" y cuando "!"
digamos que tenemos una aplicación simple basada en UIKit. tenemos algo de código en nuestro controlador de vista y queremos presentar un nuevo controlador de vista encima. y debemos decidir insertar la nueva vista en la pantalla usando el controlador de navegación.
Como sabemos, cada instancia de ViewController tiene un controlador de navegación de propiedad. Si está creando una aplicación basada en un controlador de navegación, esta propiedad del controlador de vista principal de su aplicación se configura automáticamente y puede usarla para empujar o abrir controladores de vista. Si usa una sola plantilla de proyecto de aplicación, no habrá un controlador de navegación creado automáticamente para usted, por lo que el controlador de vista predeterminado de su aplicación no tendrá nada almacenado en la propiedad navigationController.
Estoy seguro de que ya adivinó que este es exactamente un caso para un tipo de datos opcional. Si marca UIViewController, verá que la propiedad se define como:
Así que volvamos a nuestro caso de uso. Si sabe con certeza que su controlador de vista siempre tendrá un controlador de navegación, puede continuar y forzar su desenvuelto:
Cuando pones un! detrás del nombre de la propiedad le dices al compilador que no me importa que esta propiedad sea opcional, sé que cuando este código se ejecuta siempre habrá un almacén de valor, así que trata este Opcional como un tipo de datos normal. Bueno, ¿no es agradable? Sin embargo, ¿qué pasaría si no hay un controlador de navegación en su controlador de vista? Si sugieres que siempre habrá un valor almacenado en navigationController, ¿estaba mal? Tu aplicación fallará. Tan simple y feo como eso.
¿Qué tal si no está seguro de que siempre habrá un controlador de navegación? ¿Entonces puedes usar? en vez de una !:
Que ? detrás del nombre de la propiedad le dice al compilador que no sé si esta propiedad contiene nil o un valor, así que: si tiene valor, úselo y, de lo contrario, solo considere la expresión completa nil.¿Efectivamente el? le permite usar esa propiedad solo en el caso de que haya un controlador de navegación. No si cheques de cualquier tipo o fundiciones de cualquier tipo. Esta sintaxis es perfecta cuando no le importa si tiene un controlador de navegación o no, y quiere hacer algo solo si lo hay.
Muchísimas gracias a Fantageek
fuente
Son dos formas diferentes de Downcasting en Swift.
(
as?
) , que se sabe que es la forma condicional , devuelve un valor opcional del tipo al que está intentando abatir.(
as!
) , que se conoce como la forma forzada , intenta el abatido y desenvuelve el resultado como una sola acción compuesta.Para obtener más detalles, consulte la sección Type Casting de la documentación de Apple.
fuente
Quizás este ejemplo de código ayude a alguien a asimilar el principio:
fuente
El primero es un "reparto condicional" (busque en "operadores de fundición de tipos" en la documentación que he vinculado) . Si la conversión tiene éxito, el valor de la expresión se envuelve en un opcional y se devuelve; de lo contrario, el valor devuelto es nulo.
El segundo significa que OptionalString podría ser un objeto de cadena o podría ser nulo.
Más información encontrada en esta pregunta relacionada .
fuente
Puede ser más fácil recordar el patrón para estos operadores en Swift como:
!
implica "esto podría atrapar", mientras que?
indica "esto podría ser nulo".consulte: https://developer.apple.com/swift/blog/?id=23
fuente
Soy novato en Swift y escribo este ejemplo tratando de explicar lo que entiendo sobre 'opcionales'. Si me equivoco, corrígeme.
Gracias.
(1):
obj.lastName = obj.lName as! String
vs
(2):
obj.lastName = obj.lName as? String
Respuesta: (1) Aquí el programador está seguro de que
“obj.lName”
contiene un objeto de tipo cadena. Así que dale ese valor a“obj.lastName”
.Ahora, si el programador es correcto, significa que
"obj.lName"
es un objeto de tipo cadena, entonces no hay problema. "obj.lastName" se establecerá en el mismo valor.Pero si el programador está equivocado significa
"obj.lName"
que no es un objeto de tipo cadena, es decir, contiene algún otro tipo de objeto como "NSNumber", etc. Entonces CRASH (Error de tiempo de ejecución).(2) El programador no está seguro de que
“obj.lName”
contenga un objeto de tipo cadena o cualquier otro objeto de tipo. Así que establezca ese valor en“obj.lastName”
si es de tipo cadena.Ahora, si el programador es correcto, significa que
“obj.lName”
es un objeto de tipo cadena, entonces no hay problema.“obj.lastName”
se establecerá en el mismo valor.Pero si el programador está equivocado significa que obj.lName no es un objeto de tipo cadena, es decir, contiene algún otro tipo de objeto como
"NSNumber"
etc. Luego“obj.lastName”
se establecerá en el valor nulo. Entonces, No Crash (Feliz :)fuente