Categories
Swift Development

100 Dias de Swift Día 7

Estas son mis notas para el curso de swift https://www.hackingwithswift.com/100

Entrada anterior

“Energy and persistence conquer all things”

Benjamin Franklin 

«Energía y tenacidad, conquistan todas las cosas»

Benjamin Franklin

Closures, part two

Esta es la segunda parte del tema de closures y aquí es donde las cosas se vuelven mas complejas.

Using closures as parameters when they accept parameters

Anteriormente usamos «() -> Void» para pasar un closure que no acepta parámetros y nos regresa nada, pero ahora especificaremos un tipo de valor dentro de los paréntesis

func viajar(acción: (String) -> Void) {
     print("Estoy listo para partir.")
     acción("CDMX")
     print("¡Ya llegue!")
 }

viajar { (lugar: String) in
    print("voy para \(lugar) en mi auto")
}

Recuerda los nombres de los parámetros en los closures se indican dentro de las llaves

Using closures as parameters when they return values

De la misma manera podemos remplazar Void por un valor para que nuestra Closure regrese y luego usarlo dentro de la función.

func viajar(acción: (String) -> String) {
     print("Estoy listo para partir.")
     let adondeVas = acción("CDMX")
     print(adondeVas)
     print("¡Ya llegue!")
 }

viajar { (lugar: String) -> String in
    return "voy para \(lugar) en mi auto"
}

Shorthand parameter names

Hemos creado una función que acepta un closure como parámetro que a su vez acepta una String parámetro y regresa una String

Como Swift sabe que nuestro parámetro es una String y que estamos regresando una String podemos simplificar nuestra expresión de esta forma

//Sin especificar el tipo de parametro
viajar { lugar -> String in
    return "voy para \(lugar) en mi auto"
}

//Sin especificar el tipo de valor que retorna
viajar { lugar  in
    return "voy para \(lugar) en mi auto"
}

Closures with multiple parameters

También es posible utilizar Closures con multiples parámetros

func viajar(acción: (String, Int) -> String) {
     print("Estoy listo para partir.")
     let adondeVas = acción("CDMX", 60)
     print(adondeVas)
     print("¡Ya llegue!")
 } 

viajar { (lugar, km)  in
    return "voy para \(lugar) a \(km)km/hora en mi auto"
}

//version simplificada
viajar {
    return "voy para \($0) a \($1)km/hora en mi auto"
}
 

Como puedes ver en el segundo ejemplo es incluso posible simplificar aun mas la expresión usando nombres de parámetros acortados «$0» y «$1» aun así muchas personas evitan usarlos pues pueden dificultar la legibilidad de tu código.

Returning closures from functions

De la misma forma que podemos pasar closures como parámetros en una función, también podemos devolverlas como respuesta de una función.

La sintaxis aquí es un poco confusa por que usamos dos veces «->»

En el siguiente ejemplo creamos la función viajar que no acepta parámetros pero regresa un closure, este closure acepta una string y regresa nada como respuesta.

func viajar() -> (String) -> Void {
    return {
        print("Voy a \($0)")
    }
}
//función sin parámetros devuelve como respuesta un closure que acepta una string y devuelve como respuesta nada 

Ahora podemos llamar a viajar para obtener esa closure y luego usarla

let resultado = viajar()
resultado("Guadalajara")

Ahora técnicamente podemos llamar directamente a la closure pero la verdad no es muy recomendado


let resultado = viajar()("Guadalajara")

Capturing values

Si usas un valor externo dentro de tu closure, swift lo captura, esto quiere decir que lo guarda junto tu closure.

Modifiquemos nuestra closure en viajar para contar cuantas veces es llamada.

func viajar() -> (String) -> Void {
    var contador = 1
    return {
        print("Por \(contador)vez  Voy a \($0)")
        contador += 1
    }
}

Ahora cuando llamemos este closure podremos ver que el valor del contador es conservado

let resultado = viajar()
 
resultado("Guadalajara")
resultado("Guadalajara")
resultado("Guadalajara")
¡Genial! ¿no?

Resumen

Puedes asignar closures a variables y luego llamarlas

Los closures pueden aceptar parámetros y responder con valores, como una función normal

Puedes pasar closures como parámetros en una función, estas closures pueden tener sus propios parámetros y regresar respuestas con sus propios valores

Si el ultimo parámetro de una fungino es una closure, puedes usar una sintaxis reducida

Swift provee de manera automática nombres cortos para los parámetros de tu closure como $0 y $1

Sí usas valores externos en una closure, estos son capturados y guardados. para que puedas hacer referencia a ellos después

//y así terminamos con closures un tema bastante complejo pero que es usado mucho en SwiftUI veremos que tal en UIKIT

Referencias

https://www.hackingwithswift.com/100/7

https://www.hackingwithswift.com/100

Proximo día

Categories
Swift Development

100 Dias de Swift Día 6

Día 6

Estas son mis notas para el curso de Swift https://www.hackingwithswift.com

Entrada anterior

“you can’t expect to hit the jackpot if you don’t put a few nickels in the machine.”

Flip Wilson’s law

«No esperes darle al premio gordo, sin antes poner un par de monedas en la maquina»

Flip Wilson’s law

Closures, part one

Este tema es la principal razón por la que decidí volver a a retomar las lecciones básicas de Swift este tema se me había complicado bastante y no lo entendí al 100% la primera vez

Creating basic closures

Swift nos deja crear funciones como si fueran cualquier otro tipo de dato como Strings o Int, asignarla a una variable e incluso pasar esta función a otra función como parámetro.

Comencemos un simple ejemplo

let manejar = {
    print("Estoy manejando un auto")
}

Esto crea una función sin nombre que ahora podemos llamar a esa función con el nombre de la constante que creamos

manejar()

Accepting parameters in a closure

Aceptar parámetros en un «closure» es posible pero de forma un poco diferente al de una función , los parámetros se listan dentro de las llaves, dentro de paréntesis y seguidos de la palabra reservada «in»

let manejar = { (destino: String) in 
    print("Estoy manejando a \(destino) en un auto")
}

Una de las diferencias entre closures y functions es que closures no necesitan etiquetas para los parámetros

Returning values from a closure

Closures también pueden regresar valores, de manera similar a los parámetros, solo debemos indicarlos antes del «in» y usar «return» como en una función normal

 let manejar = { (destino: String) -> String in
     return "Estoy manejando a \(destino) en un auto"
 }
 
let mensaje = manejar("Pachuca")
print(mensaje)

Closures as parameters

Los closures pueden ser usados como parámetros dentro de una función, pero la sintaxis puede ser complicada

let manejar = {
    print("Estoy manejando un auto")
}

Si queremos pasar ese closure en una función debemos especificar el parámetro como «( ) -> Void». Eso significa que que no acepta parámetros y no regresa nada.

 let manejar = {
     print("Estoy manejando en un auto")
 }
 
 func viajar(acción: () -> Void) {
     print("Estoy listo para partir.")
     acción()
     print("¡Ya llegue!")
 }

 viajar(acción: manejar)

Trailing closure syntax

Si el ultimo parámetro de tu función es un closures Swift te permite pasarlo de manera especial esto es llamado trailing closure syntax. En lugar de pasar tu closure como un parámetro, lo pasas directo después de la función entre llaves.

 func viajar(acción: () -> Void) {
     print("Estoy listo para partir.")
     acción()
     print("¡Ya llegue!")
 }
 
 viajar(){
    print("Estoy viajando en un Barco")
 }

De hecho como esta función no tiene ningún parámetro podemos omitir los paréntesis

 viajar{
    print("Estoy viajando en un Avión")
 }

// Aquí termina la parte 1 mañana continuare la parte 2 y  hare el resumen de ambas 

Referencias

https://www.hackingwithswift.com/100

https://www.hackingwithswift.com/100/6

Proximo día