Clausuras
Clausuras
Clausuras es una lección gratuita de Swift Academy en CoddyKit. Esta es la lección 1 de 1. Puedes leer la lección completa abajo gratuitamente — luego la practicas en el navegador con un editor de código integrado y un tutor de IA 24/7. Forma parte de la ruta de aprendizaje de Swift Academy, y tu progreso se sincroniza en la web y la app de CoddyKit. El curso de Swift Academy incluye 1 lecciones en total.
Introducción
Hola:
Los closures son bloques de código independientes. Un closure se pasa como parámetro al código o puede utilizarse dentro de él.
Un closure es un tipo de función. Puede utilizarse pasándolo dentro del código. Son similares a las lambdas de otros lenguajes de programación.
Gestión de memoria
Uno de los aspectos más importantes es que un closure puede capturar y almacenar los valores de las constantes y variables del contexto en el que se define.
Este almacenamiento se conoce como closing-over.
Swift gestiona la memoria por nosotros durante este almacenamiento.
Tipos de closure
Existen varios tipos de closure.
- Las funciones globales son closures con nombre y no conservan ningún valor.
- Las funciones anidadas pueden conservar los valores del nombre y de la función que las envuelve.
- Las expresiones de closure, por su parte, son closures anónimos y pueden almacenar datos del contexto que las rodea mediante una sintaxis sencilla.
Sintaxis de los closures
Se intenta simplificar la sintaxis de los closures tanto como sea posible. Los aspectos más importantes son los siguientes.
- Los parámetros de los closures pueden inferirse.
- Los valores de retorno pueden inferirse.
- Un closure puede devolver un valor en una sola línea.
- Los nombres de los argumentos pueden expresarse mediante abreviaturas como $ 0 o $ 1.
- Se puede utilizar la sintaxis de trailing closure.
Información
Las expresiones de closure consisten en escribir los closures en línea, priorizando la sintaxis y la simplicidad.
Sintaxis de un closure
A continuación se muestra la sintaxis de un closure en el código de ejemplo.
{ (parameters) -> return type in
statements
}
func backward(_ s1: String, _ s2: String) -> Bool {
return s1 > s2
}
//If we didn't use closures, our code structure would be as follows.
var reversedNames = names.sorted(by: backward)
Sintaxis de un closure
Sin embargo, al utilizar un closure no necesitamos definir un closure global con nombre innecesario de este tipo.
Basta con definir una expresión de closure sencilla como parámetro. Veamos el ejemplo.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)
///sorted method takes closure as parameter.Palabra clave in
La palabra clave in indica que comienza el cuerpo del closure.
Antes de la palabra clave in deben definirse los parámetros que recibe el closure y el tipo de retorno.
Inferencia de tipos a partir del contexto
Inferencia de tipos a partir del contexto
En el ejemplo anterior, la expresión de closure puede entenderse mediante la inferencia de los parámetros y del tipo de retorno, ya que el método sorted recibe un closure.
Por lo tanto, no es necesario definirlos explícitamente.
En este ejemplo, se entenderá que, como los valores del array names son Strings, los parámetros que recibe el closure serán de tipo String.
Del mismo modo, como el closure correspondiente necesita un tipo Bool para ordenar, el tipo de retorno se inferirá como Bool.
Ejemplo
Esto simplifica el uso de la siguiente manera.
La flecha también puede omitirse del código al inferir el tipo de retorno.
let names = ["Chris", "Alex", "Ewa", "Barry", "Daniella"]
let reversedNames = names.sorted(by: { (s1: String, s2: String) -> Bool in
return s1 > s2
})
print(reversedNames)Sintaxis abreviada
Es preferible utilizar la sintaxis larga en lugar de la abreviada para no confundir a quienes leen el código.
La sintaxis anterior puede abreviarse aún más.
El valor de retorno puede abreviarse en la expresión de closure eliminando la palabra clave return.
/*
In this example, the return keyword has been extracted.
It already has single expression.
There is no need to express it as an extra with return.
*/
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )
print(reversedNames)Ejemplo
En este ejemplo se ha omitido la palabra clave return.
Ya hay una sola expresión, por lo que no es necesario indicarla explícitamente mediante return.
reversedNames = names.sorted(by: { s1, s2 in s1 > s2 } )Abreviatura de nombres
La sintaxis puede abreviarse aún más. En el ejemplo anterior indicamos que el closure recibe dos parámetros, incluidos s1 y s2. Sus tipos se infieren.
Ahora podemos evitar expresar estos parámetros mediante abreviaturas y definirlos por separado.
Además, como no hay una definición de parámetros ni un valor de retorno explícito, también se puede omitir la palabra clave in.
let names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: { $0 > $1 } )
print(reversedNames)
// In this example $0 will shortcut the first parameter and $1 will shortcut the second parameter.Ejemplo abreviado
var names = ["Coddy", "Kit"]
let reversedNames = names.sorted(by: >)
print(reversedNames)
// Greater than operator takes two parameters and the rotation type is squat.TRAILING CLOSURE
Trailing Closure
Si el closure que se pasa a una función es el argumento final de esta y la expresión de closure es larga, puede resultar más útil escribirla mediante la sintaxis de trailing closure.
Podemos utilizar trailing closure como una forma abreviada de la sintaxis. Se utiliza para aumentar la legibilidad del código.
El último parámetro de la mayoría de los métodos de iOS es un closure.
Parámetro final
Por ejemplo, en este caso, el parámetro final es un closure.
class Animator {
class func animate(withDuration duration: Double, animations: () -> Void) {
animations()
}
}
class MyViewController {
func start() {
// With the traditional method, we can call this fund as follows.
Animator.animate(withDuration: 1, animations: { [unowned self] in
print("red")
})
}
}
MyViewController().start()Como el código anterior es menos legible, puede escribirse de la siguiente manera
Como el código anterior es menos legible, puede escribirse de la siguiente manera.
import Foundation
Thread.sleep(forTimeInterval: 1)
print("Background color changed to red")Ejemplo
Al utilizar la sintaxis de trailing closure, no es necesario escribir la etiqueta del argumento.
Esto se debe a que los closures ahora forman parte de la llamada a la función.
func someFunctionThatTakesAClosure(closure: () -> Void) {
// function body goes here
}
// Here's how you call this function without using a trailing closure:
someFunctionThatTakesAClosure(closure: {
// closure's body goes here
})
// Here's how you call this function with a trailing closure instead:
someFunctionThatTakesAClosure() {
// trailing closure's body goes here
}Sintaxis
En realidad, podemos considerar la sintaxis de trailing closure como una forma abreviada de la sintaxis. Hace que el código sea más legible.
/*
In the example below, animations
are expressed as closure.
*/
public class func animate(withDuration: TimeInterval, animations: () -> Void)
// In traditional usage, we need to make a call like the following.
UIView.animate(withDuration: 1, animations: { [unowned self] in
self.view.backgroundColor = UIColor.red
})
/*
In this way, both the readability of the code
increases and we avoid the use of extra brackets.
If it is as above and the last parameter of the method
is closure, Swift allows to make a call like the one below.
*/
UIView.animate(withDuration: 1) { [unowned self] in
self.view.backgroundColor = UIColor.red
}Podemos utilizar el código siguiente para probar el código
Podemos utilizar el código siguiente para probar el código.
func greetThenRunClosure(name: String, closure: () -> ()) {
print("Hello, \(name)!")
closure()
}
greetThenRunClosure(name: "Paul") {
print("The closure was run")
}Captura de valores por closures
Captura de valores por closures
Un closure puede capturar los valores de las variables del entorno que lo engloba. Incluso es posible cambiar el valor de estas variables desde el propio cuerpo del closure y acceder a ellas.
Aunque estas variables ya no se encuentren en el ámbito original en el que se definieron.
Continuación
En general, estos datos pueden conservarse en funciones anidadas junto con expresiones de closure. Estas pueden almacenar los datos de la función externa.
func makeIncrementer(forIncrement amount: Int) -> () -> Int {
var runningTotal = 0
func incrementer() -> Int {
runningTotal += amount
return runningTotal
}
return incrementer
}
let incrementByTen = makeIncrementer(forIncrement: 10)
print(incrementByTen())
// returns a value of 10
print(incrementByTen())
// returns a value of 20
print(incrementByTen())
// returns a value of 30Continuación
Si asigna un closure como propiedad de una clase, este comenzará a mantener una referencia a la instancia que lo contiene.
Por lo tanto, se establecerá un ciclo de referencias fuertes entre el closure y la instancia.
Se debe prestar especial atención a las fugas de memoria.
Advertencia
Los closures y las funciones son tipos de referencia.
@escaping
Este uso puede ser necesario en muchos casos en los que el closure se utiliza de forma asíncrona.
En las primeras versiones de Swift (1 y 2), los closures de los parámetros de Swift eran escapables y después pasaron a ser no escapables. Si necesitábamos pasar un closure no escapable, teníamos que especificarlo explícitamente.
En las versiones posteriores, los parámetros closure se hicieron no escapables para obtener una ventaja en cuanto al uso de memoria.
Ahora, si queremos definir un closure escapable, debemos especificarlo mediante la palabra clave @escaping.
Palabra clave @ESCAPING
Palabra clave @ESCAPING
Si queremos poder llamar a los closures asignados a una función después de que esta devuelva el control, debemos utilizar la palabra clave @escaping.
Los closures definidos como parámetros de una función son tipos de referencia, pero no incrementan el recuento de referencias. Esto se debe a que, al realizar la llamada, finaliza la vida útil de este closure y no es necesario aumentar el recuento de referencias.
Sin embargo, si necesitamos utilizar como parámetro un closure después de llamar a una función, puede ser necesario expresarlo mediante la palabra clave @escaping.
nonEscaping
Primero, veamos cómo funciona un closure no escapable.
Cuando este closure se pasa como parámetro a la función, se procesa en el cuerpo de la función y luego se devuelve al compilador.
Después de que la función devuelve el control, es decir, una vez completada la ejecución, el closure queda fuera de su ámbito y se libera de la memoria.
Uso de un closure escapable
Uso de un closure escapable
Cuando una función closure se pasa como argumento, continúa conservándose incluso después de que la función devuelva el control y finalice la ejecución.
Además, ocupa espacio en la memoria hasta que se ejecuta el closure. Existen varios tipos de closures escapables.
Enhorabuena
Enhorabuena 🎉
Hemos llegado al final de nuestra lección.
Nos vemos en la próxima lección 😎

Preguntas frecuentes
¿La lección «Clausuras» es gratis?
Sí — el texto completo de «Clausuras» es gratis para leer aquí en la web. Para practicarla de forma interactiva (editor de código integrado y tutor de IA 24/7) y desbloquear el resto del curso de Swift Academy, actualiza a CoddyKit PRO. El curso de Swift Academy incluye 1 lecciones en total.
¿Qué aprenderé en «Clausuras»?
Clausuras Practicas Swift Academy con código real que ejecutas directamente en el navegador, y un tutor de IA 24/7 responde tus preguntas mientras trabajas en la lección.
¿Necesito experiencia previa para empezar Swift Academy?
No se requiere experiencia previa. Swift Academy en CoddyKit está estructurado para principiantes hasta estudiantes avanzados, así que puedes empezar aquí o desde el inicio y avanzar a tu ritmo. Esta es la lección 1 de 1.
¿Cuánto tiempo toma la lección «Clausuras»?
La mayoría de las lecciones de CoddyKit toman alrededor de 5–10 minutos. Cada una es compacta e interactiva, así que avanzas constantemente y retomas exactamente por donde dejaste en la web y la app.
¿Puedo escribir y ejecutar código en esta lección de Swift Academy?
Sí. Cada lección de Swift Academy incluye un editor de código integrado, así que escribes y ejecutas código real directamente en tu navegador y obtienes retroalimentación instantánea de IA — sin configuración local necesaria.