ios - sport - Swift: Pruebas opcionales para nada
suzuki swift rendimiento (11)
Estoy usando Xcode 6 Beta 4. Tengo esta extraña situación en la que no puedo encontrar la manera adecuada de probar los opcionales.
Si tengo un xyz opcional, es la forma correcta de probar:
if (xyz) // Do something
o
if (xyz != nil) // Do something
Los documentos dicen que lo haga de la primera manera, pero he descubierto que a veces, la segunda forma es necesaria y no genera un error de compilación, pero otras veces, la segunda forma genera un error de compilación.
Mi ejemplo específico es usar el analizador GData XML puenteado para pasar rápidamente:
let xml = GDataXMLDocument(
XMLString: responseBody,
options: 0,
error: &xmlError);
if (xmlError != nil)
Aquí, si acabo de hacer:
if xmlError
siempre volvería verdadero. Sin embargo, si lo hago:
if (xmlError != nil)
luego funciona (como funciona en Objective-C).
¿Hay algo con el GData XML y la forma en que trata los opcionales que me falta?
Ahora puedes hacer lo siguiente con rapidez, lo que te permite recuperar un poco del objetivo-c if nil else
if textfieldDate.text?.isEmpty ?? true {
}
Aunque todavía debe comparar explícitamente un opcional con nil
o usar un enlace opcional para extraer adicionalmente su valor (es decir, los opcionales no se convierten implícitamente en valores booleanos), vale la pena señalar que Swift 2 ha agregado el enunciado de guard
para ayudar a evitar la pirámide de fatalidad cuando se trabaja con múltiples valores opcionales.
En otras palabras, sus opciones ahora incluyen la comprobación explícita de nil
:
if xyz != nil {
// Do something with xyz
}
Encuadernación opcional:
if let xyz = xyz {
// Do something with xyz
// (Note that we can reuse the same variable name)
}
Y declaraciones de guard
:
guard let xyz = xyz else {
// Handle failure and then exit this code block
// e.g. by calling return, break, continue, or throw
return
}
// Do something with xyz, which is now guaranteed to be non-nil
Tenga en cuenta cómo el enlace opcional ordinario puede conducir a una mayor sangría cuando hay más de un valor opcional:
if let abc = abc {
if let xyz = xyz {
// Do something with abc and xyz
}
}
Puede evitar este anidamiento con declaraciones de guard
:
guard let abc = abc else {
// Handle failure and then exit this code block
return
}
guard let xyz = xyz else {
// Handle failure and then exit this code block
return
}
// Do something with abc and xyz
De la guide programación rápida
Si declaraciones y desempaquetado forzoso
Puede usar una instrucción if para averiguar si una opción contiene un valor. Si un opcional tiene un valor, se evalúa como verdadero; si no tiene ningún valor, se evalúa como falso.
Entonces, la mejor manera de hacerlo es
// swift > 3
if xyz != nil {}
y si está utilizando xyz
en la sentencia if. Es posible desplegar xyz
en la instrucción if en variable constante. Por lo tanto, no necesita desenvolver todos los lugares en la instrucción if donde se usa xyz
.
if let yourConstant = xyz{
//use youtConstant you do not need to unwrap `xyz`
}
Esta convención es sugerida por apple
y será seguida por devlopers.
En lugar de hacerlo, el operador ternario podría ser útil cuando desee obtener un valor basado en si algo es nulo:
func f(x: String?) -> String {
return x == nil ? "empty" : "non-empty"
}
En xcode beta 5, ya no te dejan hacer
var xyz : NSString?
if xyz {
//Do Something
}
Produce un error "does not conform to protocol ''BooleanType.Protocol''"
Tienes que hacer una de estas declaraciones:
if xyz != nil {
//Do Something
}
if let xy = xyz {
//Do Something
}
Otro enfoque además de usar declaraciones if
o guard
para hacer el enlace opcional es extender Optional
con:
extension Optional {
func ifValue(_ valueHandler: (Wrapped) -> Void) {
switch self {
case .some(let wrapped): valueHandler(wrapped)
default: break
}
}
}
ifValue
recibe un cierre y lo llama con el valor como argumento cuando el opcional no es nulo. Se usa de esta manera:
var helloString: String? = "Hello, World!"
helloString.ifValue {
print($0) // prints "Hello, World!"
}
helloString = nil
helloString.ifValue {
print($0) // This code never runs
}
Sin embargo, probablemente debería usar un if
o guard
ya que esos son los enfoques más convencionales (por lo tanto, familiares) utilizados por los programadores de Swift.
Para agregar a las otras respuestas, en lugar de asignar a una variable de nombre diferente dentro de una condición if
:
var a: Int? = 5
if let b = a {
// do something
}
puedes reutilizar el mismo nombre de variable así:
var a: Int? = 5
if let a = a {
// do something
}
Esto podría ayudarlo a evitar quedarse sin nombres de variables creativas ...
Esto aprovecha el sombreado variable compatible con Swift.
Si tiene condiciones y desea desenvolver y comparar, ¿qué le parece aprovechar la evaluación de cortocircuito de la expresión booleana compuesta como en
if xyz != nil && xyz! == "some non-nil value" {
}
Por supuesto, esto no es tan legible como algunas de las otras publicaciones sugeridas, pero hace el trabajo de manera un tanto breve que las otras soluciones sugeridas.
Una de las formas más directas de usar opcionales es la siguiente:
¿Asumiendo que xyz
es de tipo opcional, como Int?
por ejemplo.
if let possXYZ = xyz {
// do something with possXYZ (the unwrapped value of xyz)
} else {
// do something now that we know xyz is .None
}
De esta forma, ambos pueden probar si xyz
contiene un valor y, de ser así, trabajar inmediatamente con ese valor.
Con respecto a su error de compilación, el tipo UInt8
no es opcional (note no ''?'') Y por lo tanto no se puede convertir a nil
. Asegúrese de que la variable con la que está trabajando sea opcional antes de tratarla como tal.
Swift 3.0, 4.0
Hay principalmente dos formas de verificar opcionales por cero. Aquí hay ejemplos con comparación entre ellos
1. si deja
if let
es la forma más básica de marcar opcionalmente nil. Se pueden agregar otras condiciones a esta comprobación nula, separadas por comas. La variable no debe ser nula para moverse para la siguiente condición. Si solo se requiere verificación nula, elimine las condiciones adicionales en el siguiente código.
Aparte de eso, si x
no es nulo, se ejecutará el cierre si y x_val
estará disponible dentro. De lo contrario, se desencadena el cierre else.
if let x_val = x, x_val > 5 {
//x_val available on this scope
} else {
}
2. guardia dejada
guard let
que haga cosas similares. Su objetivo principal es hacerlo lógicamente más razonable. Es como decir Asegúrese de que la variable no sea nula; de lo contrario, detenga la función . guard let
también puede hacer una verificación de condición adicional como if let
.
Las diferencias son que el valor desenvuelto estará disponible en el mismo alcance que guard let
, como se muestra en el comentario a continuación. Esto también lleva al punto de que en otro cierre, el programa tiene que salir del alcance actual, por return
, break
, etc.
guard let x_val = x, x_val > 5 else {
return
}
//x_val available on this scope
var xyz : NSDictionary?
// case 1:
xyz = ["1":"one"]
// case 2: (empty dictionary)
xyz = NSDictionary()
// case 3: do nothing
if xyz { NSLog("xyz is not nil.") }
else { NSLog("xyz is nil.") }
Esta prueba funcionó como se esperaba en todos los casos. Por cierto, no necesitas los corchetes ()
.