tipos tag que para name keywords etiquetas etiqueta ejemplos basicos swift2 guard-statement

swift2 - que - meta tag basicos



Palabra clave de guardia de Swift (13)

Swift 2 introdujo la palabra clave guard , que podría usarse para garantizar que varios datos estén configurados listos para funcionar. Un ejemplo que vi en este sitio web demuestra una función submitTapped:

func submitTapped() { guard username.text.characters.count > 0 else { return } print("All good") }

Me pregunto si usar guard es diferente de hacerlo a la antigua, usando una condición if . ¿Ofrece beneficios que no podría obtener con un simple cheque?


De la documentación de Apple:

Declaración de guardia

Se utiliza una declaración de guardia para transferir el control del programa fuera de un alcance si no se cumplen una o más condiciones.

Synatx:

guard condition else { statements }

Ventaja:

1. Al usar la declaración de guard podemos deshacernos de condicionales profundamente anidados cuyo único propósito es validar un conjunto de requisitos.

2. Fue diseñado específicamente para salir temprano de un método o función.

si usa si se deja a continuación es el código cómo se ve.

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in if error == nil { if let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 { if let data = data { //Process Data Here. print("Data: /(data)") } else { print("No data was returned by the request!") } } else { print("Your request returned a status code other than 2XX!") } } else { print("Error Info: /(error.debugDescription)") } } task.resume()

Con la protección, puede transferir el control fuera de alcance si no se cumplen una o más condiciones.

let task = URLSession.shared.dataTask(with: request) { (data, response, error) in /* GUARD: was there an error? */ guard (error == nil) else { print("There was an error with your request: /(error)") return } /* GUARD: Did we get a successful 2XX response? */ guard let statusCode = (response as? HTTPURLResponse)?.statusCode, statusCode >= 200 && statusCode <= 299 else { print("Your request returned a status code other than 2XX!") return } /* GUARD: was there any data returned? */ guard let data = data else { print("No data was returned by the request!") return } //Process Data Here. print("Data: /(data)") } task.resume()

Referencia:

1. Swift 2: Salga temprano con guardia 2. Udacity 3. Declaración de guardia


Cuando usar guardias

Si tiene un controlador de vista con algunos elementos UITextField o algún otro tipo de entrada del usuario, notará inmediatamente que debe desenvolver el textField.text opcional para acceder al texto (¡si lo hay!). isEmpty no le servirá de nada aquí, sin ninguna entrada, el campo de texto simplemente devolverá nil.

Entonces, tiene algunos de estos que desenvuelve y finalmente pasa a una función que los publica en un punto final del servidor. No queremos que el código del servidor tenga que tratar con valores nulos o enviar por error valores no válidos al servidor, por lo que primero desenvolveremos esos valores de entrada con guardia.

func submit() { guard let name = nameField.text else { show("No name to submit") return } guard let address = addressField.text else { show("No address to submit") return } guard let phone = phoneField.text else { show("No phone to submit") return } sendToServer(name, address: address, phone: phone) } func sendToServer(name: String, address: String, phone: String) { ... }

Notará que nuestra función de comunicación del servidor toma valores de cadena no opcionales como parámetros, por lo tanto, la protección se desenvuelve de antemano. El desenvolvimiento es un poco intuitivo porque estamos acostumbrados a desenvolver si se deja que desenvuelva los valores para usar dentro de un bloque. Aquí la declaración de protección tiene un bloque asociado, pero en realidad es un bloque else, es decir, lo que se hace si falla el desenvolvimiento: los valores se desenvuelven directamente en el mismo contexto que la declaración en sí.

// separación de intereses

Sin guardia

Sin usar guardia, terminaríamos con una gran pila de código que se asemeja a una pirámide de fatalidad . Esto no se escala bien para agregar nuevos campos a nuestro formulario o crear un código muy legible. La sangría puede ser difícil de seguir, particularmente con tantas otras declaraciones en cada bifurcación.

func nonguardSubmit() { if let name = nameField.text { if let address = addressField.text { if let phone = phoneField.text { sendToServer(name, address: address, phone: phone) } else { show("no phone to submit") } } else { show("no address to submit") } } else { show("no name to submit") } }

Sí, incluso podríamos combinar todo esto si dejamos declaraciones en una sola declaración separada por comas, pero perderíamos la capacidad de descubrir qué declaración falló y presentar un mensaje al usuario.

https://thatthinginswift.com/guard-statement-swift/


A diferencia de if , guard crea la variable a la que se puede acceder desde fuera de su bloque. Es útil desenvolver muchos Optional .


Al igual que una declaración if, guard ejecuta declaraciones basadas en un valor booleano de una expresión. A diferencia de una declaración if, las declaraciones de guardia solo se ejecutan si no se cumplen las condiciones. Puede pensar en la guardia más como una Afirmación, pero en lugar de estrellarse, puede salir con gracia.

consulte: http://ericcerney.com/swift-guard-statement/


Al leer este artículo , noté grandes beneficios al usar Guard

Aquí puede comparar el uso de guardia con un ejemplo:

Esta es la parte sin guardia:

func fooBinding(x: Int?) { if let x = x where x > 0 { // Do stuff with x x.description } // Value requirements not met, do something }

  1. Aquí está poniendo su código deseado dentro de todas las condiciones

    Es posible que no vea inmediatamente un problema con esto, pero podría imaginar lo confuso que podría ser si estuviera anidado con numerosas condiciones que todas debían cumplirse antes de ejecutar sus declaraciones

La forma de limpiar esto es hacer primero cada uno de sus controles y salir si no se cumple alguno. Esto permite comprender fácilmente qué condiciones harán que esta función salga.

Pero ahora podemos usar guardia y podemos ver que es posible resolver algunos problemas:

func fooGuard(x: Int?) { guard let x = x where x > 0 else { // Value requirements not met, do something return } // Do stuff with x x.description }

  1. Verificando la condición que desea, no la que no desea. Esto nuevamente es similar a una afirmación. Si no se cumple la condición, se ejecuta la instrucción else de guard, que se sale de la función.
  2. Si la condición pasa, la variable opcional aquí se desenvuelve automáticamente para usted dentro del alcance que se llamó a la declaración de protección, en este caso, la función fooGuard (_ :).
  3. Está comprobando si hay casos graves temprano, haciendo que su función sea más legible y más fácil de mantener

Este mismo patrón también es válido para valores no opcionales:

func fooNonOptionalGood(x: Int) { guard x > 0 else { // Value requirements not met, do something return } // Do stuff with x } func fooNonOptionalBad(x: Int) { if x <= 0 { // Value requirements not met, do something return } // Do stuff with x }

Si todavía tiene alguna pregunta, puede leer el artículo completo: Declaración de guardia de Swift.

Terminando

Y finalmente, leyendo y probando, descubrí que si usas guardia para desenvolver cualquier opción,

esos valores sin envolver permanecen disponibles para que los use en el resto de su bloque de código

.

guard let unwrappedName = userName else { return } print("Your username is /(unwrappedName)")

Aquí el valor sin envolver estaría disponible solo dentro del bloque if

if let unwrappedName = userName { print("Your username is /(unwrappedName)") } else { return } // this won''t work – unwrappedName doesn''t exist here! print("Your username is /(unwrappedName)")


Con el uso de guardia nuestra intención es clara. no queremos ejecutar el resto del código si esa condición particular no se cumple. aquí también podemos extender la cadena, consulte el siguiente código:

guard let value1 = number1, let value2 = number2 else { return } // do stuff here


Cuando se cumple una condición usando guard , expone las variables declaradas dentro del bloque de guard al resto del bloque de código, llevándolas a su alcance. Lo cual, como se dijo anteriormente, sin duda será útil con declaraciones anidadas if let .

Tenga en cuenta que el guardia requiere una devolución o un lanzamiento en su declaración else.

Analizando JSON con Guard

A continuación se muestra un ejemplo de cómo se podría analizar un objeto JSON usando guard en lugar de if-let. Este es un extracto de una entrada de blog que incluye un archivo de juegos que puedes encontrar aquí:

Cómo usar Guard en Swift 2 para analizar JSON

func parseJSONWithGuard(data : [String : AnyObject]) throws -> Developer { guard let firstname = data["First"] as? String else { return Developer() // we could return a nil Developer() } guard let lastname = data["Last"] as? String else { throw ParseError.BadName // or we could throw a custom exception and handle the error } guard let website = data["WebSite"] as? String else { throw ParseError.BadName } guard let iosDev = data["iosDeveloper"] as? Bool else { throw ParseError.BadName } return Developer(first: firstname, last: lastname, site: website, ios: iosDev) }

descargar parque infantil: parque infantil de guardia

Más información:

Aquí hay un extracto de la Guía del lenguaje de programación Swift:

Si se cumple la condición de la declaración de guarda, la ejecución del código continúa después de la llave de cierre de la declaración de guarda. Las variables o constantes a las que se les asignaron valores mediante un enlace opcional como parte de la condición están disponibles para el resto del bloque de código en el que aparece la instrucción de protección.

Si no se cumple esa condición, se ejecuta el código dentro de la rama else. Esa rama debe transferir el control para salir del bloque de código en el que aparece esa declaración de protección. Puede hacer esto con una declaración de transferencia de control como return, break o continue, o puede llamar a una función o método que no devuelve, como como fatalError ().


Declaración de guardia va a hacer. es un par de diferentes

1) me permite reducir la declaración anidada if
2) es aumentar mi alcance que mi variable accesible

si la declaración

func doTatal(num1 : Int?, num2: Int?) { // nested if statement if let fistNum = num1 where num1 > 0 { if let lastNum = num2 where num2 < 50 { let total = fistNum + lastNum } } // don''t allow me to access out of the scope //total = fistNum + lastNum }

Declaración de guardia

func doTatal(num1 : Int?, num2: Int?) { //reduce nested if statement and check positive way not negative way guard let fistNum = num1 where num1 > 0 else{ return } guard let lastNum = num2 where num2 < 50 else { return } // increase my scope which my variable accessible let total = fistNum + lastNum }


En pocas palabras, proporciona una forma de validar los campos antes de la ejecución. Este es un buen estilo de programación, ya que mejora la legibilidad. En otros idiomas, puede verse así:

func doSomething() { if something == nil { // return, break, throw error, etc. } ... }

Pero debido a que Swift le ofrece opciones, no podemos verificar si es nulo y asignar su valor a una variable. Por el contrario, if let comprueba que no es nulo y asigna una variable para mantener el valor real. Aquí es donde entra en juego la guard . Le brinda una forma más concisa de salir temprano utilizando opciones.


Fuente: https://thenucleargeeks.com/2019/05/09/guard-in-swift/

Veamos el ejemplo para entenderlo claramente

Ejemplo 1:

func validate() { guard 3>2 else { print ("False") return } print ("True") //True } validate()

En el ejemplo anterior, vemos que 3 es mayor que 2 y se omite la declaración dentro de la cláusula guard else y se imprime True.

Ejemplo 2

func validate() { guard 1>2 else { print ("False") //False return } print ("True") } validate()

En el ejemplo anterior vemos que 1 es menor que 2 y la declaración dentro de la cláusula guard else se ejecuta y False se imprime seguido de return.

Example 3: gaurd let, unwrapping optionals through guard let func getName(args myName: String?) { guard let name = myName, !name.isEmpty else { print ("Condition is false") // Condition is false return } print("Condition is met/(name)") } getName(args: "")

En el ejemplo anterior, estamos usando guard let para desenvolver los opcionales. En la función getName hemos definido una variable de tipo string myName que es opcional. Luego usamos guard let para verificar si la variable myName es nula o no, si no se asigna a name y verificamos nuevamente, name no está vacío. Si ambas condiciones cumplen los requisitos, es decir, el bloque else se omitirá e imprimirá "Las condiciones se cumplen con el nombre".

Básicamente, estamos verificando dos cosas separadas por comas, primero desenvolviendo y opcionales, y verificando si eso satisface la condición o no.

Aquí no estamos pasando nada a la función, es decir, cadena vacía y, por lo tanto, la condición es falsa se imprime.

func getName(args myName: String?) { guard let name = myName, !name.isEmpty else { print ("Condition is false") return } print("Condition is met /(name)") // Condition is met Hello } getName(args: "Hello")

Aquí estamos pasando "Hola" a la función y puede ver que la salida se imprime "Condición se cumple Hola".


Realmente hace que el flujo de una secuencia con varias búsquedas y opciones sea mucho más conciso y claro, y reduce mucho si se anida. Vea la publicación de Erica Sadun sobre el reemplazo de Ifs . .... Podría dejarse llevar, un ejemplo a continuación:

let filteredLinks = locationsLinkedToList.filter({$0.actionVerb == movementCommand}) guard let foundLink = filteredLinks.first else {return ("<Person> cannot go in that direction.", nil, nil)} guard filteredLinks.count == 1 else {return ("<Person> cannot decide which route to take.", nil, nil)} guard let nextLocation = foundLink.toLocation else {return ("<Person> cannot go in that direction.", nil, nil)}

A ver si eso se pega.


Realmente hay dos grandes beneficios para guard . Una es evitar la pirámide de la fatalidad, como han mencionado otros, un montón de molestias if let declaraciones anidadas una dentro de la otra se mueven cada vez más hacia la derecha.

El otro beneficio es que la lógica que desea implementar es más " if not let " que " if let { } else ".

Aquí hay un ejemplo: suponga que desea implementar la accumulate : un cruce entre el map y la reduce donde le devuelve una serie de reducciones en ejecución . Aquí está con guard :

extension Sliceable where SubSlice.Generator.Element == Generator.Element { func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] { // if there are no elements, I just want to bail out and // return an empty array guard var running = self.first else { return [] } // running will now be an unwrapped non-optional var result = [running] // dropFirst is safe because the collection // must have at least one element at this point for x in dropFirst(self) { running = combine(running, x) result.append(running) } return result } } let a = [1,2,3].accumulate(+) // [1,3,6] let b = [Int]().accumulate(+) // []

¿Cómo lo escribirías sin protección, pero aún usando el first que devuelve un opcional? Algo como esto:

extension Sliceable where SubSlice.Generator.Element == Generator.Element { func accumulate(combine: (Generator.Element,Generator.Element)->Generator.Element) -> [Generator.Element] { if var running = self.first { var result = [running] for x in dropFirst(self) { running = combine(running, x) result.append(running) } return result } else { return [] } } }

El anidamiento adicional es molesto, pero tampoco es tan lógico tener el if y el else tan separados. Es mucho más legible tener la salida anticipada para el caso vacío, y luego continuar con el resto de la función como si eso no fuera una posibilidad.


Un beneficio es la eliminación de muchas declaraciones anidadas if let . Vea el video de WWDC "What''s New in Swift" alrededor de las 15:30, la sección titulada "Pyramid of Doom".