English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
En este artículo, aprenderás qué son los closures, su sintaxis y los tipos de closures en Swift mediante ejemplos.
En el artículo sobre funciones de Swift, creamos una función utilizando la palabra clave func. Sin embargo, en Swift también hay otro tipo especial de función llamado closure, que se puede definir sin usar la palabra clave func ni el nombre de la función.
Al igual que las funciones, los closures pueden aceptar parámetros y devolver valores. También contienen un conjunto de instrucciones que se ejecutan después de la llamada y pueden asignarse a variables como funciones./Constantes.
Los closures en Swift son comparables a C y Objective-C-Los bloques de código en C y las funciones anónimas en otros lenguajes de programación son bastante similares.
Las funciones globales y las funciones anidadas son básicamente closures especiales.
Las formas de closure son:
Funciones globales | Funciones anidadas | expresión de cierre |
Closures con nombre pero que no pueden capturar ningún valor. | Closures con nombre, también pueden capturar valores dentro de la función cerrada. | Closures anónimas, que utilizan una sintaxis ligera, pueden capturar valores del entorno contextual. |
Hay muchos aspectos optimizados de las closures en Swift:
se infiere el tipo de parámetro y el valor de retorno desde el contexto
se devuelve implícitamente desde un closure de una sola línea (es decir, el cuerpo del closure solo tiene una línea de código y se puede omitir return)
Se puede usar nombres de parámetros simplificados, como $0, $1(desde 0, que representa el i-ésimo parámetro...)
proporciona la sintaxis de cierre colocado al final (trailing closure syntax)
La siguiente definición de closure recibe parámetros y devuelve un tipo especificado:
{(parameters) -> return type in statements }
let simpleClosure = { print("¡Hola, Mundo!") } simpleClosure()
以上程序执行输出结果为:
¡Hola, Mundo!
La siguiente forma de closure recibe dos parámetros y devuelve un valor booleano:
{(Int, Int) -> Bool in Statement1 Statement 2 --- Statement n }
let simpleClosure:(String) -> (String) = { name in let greeting = "¡Hola, Mundo!" + "Program" return greeting } let result = simpleClosure("¡Hola, Mundo!") print(result)
以上程序执行输出结果为:
¡Hola, Mundo! Program
La expresión de cierre es una forma de construir closures inline con una sintaxis concisa. La expresión de cierre proporciona algunas optimizaciones de sintaxis que facilitan la escritura de closures.
La biblioteca estándar de Swift proporciona una función llamada sorted(by:) El método, según la función de cierre proporcionada para ordenar, ordenará los valores en el array de tipo conocido.
Después de ordenar, el método sorted(by:) devuelve un nuevo array del mismo tamaño que el array original, que contiene elementos del mismo tipo y correctamente ordenados. El array original no se modificará por el método sorted(by:)
El método sorted(by:) necesita recibir dos parámetros:
El array de tipo conocido
La función de cierre, esta función de cierre necesita recibir dos valores de tipo idéntico al tipo de los elementos del array, y devuelve un valor de tipo booleano para indicar si al finalizar el ordenamiento, el primer parámetro ingresado se encuentra antes o después del segundo parámetro. Si el valor del primer parámetro aparece antes del valor del segundo parámetro, la función de cierre de ordenamiento debe devolver truede lo contrario, devuelve false.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] // Para proporcionar la funcionalidad de ordenación mediante una función común (o una función anidada), el tipo de función de la clausura debe ser (String, String) -> Bool. func backwards(s1: String, s2: String) -> Bool { return s1 > s2 } var reversed = names.sorted(by: backwards) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
si la primera cadena (s1) es mayor que la segunda cadena (s2) y la función backwards devuelve true, lo que indica que s1debería aparecer en s2antes. Para los caracteres de una cadena, "mayor que" significa "aparece más tarde en el orden alfabético". Esto significa que la letra "B" es mayor que la letra "A", y la cadena "S" es mayor que la cadena "D". Se realizará un orden alfabético inverso, y "AT" se colocará antes de "AE".
Swift proporciona automáticamente la funcionalidad de abreviatura de nombres de parámetros para las funciones en línea, y puede usar directamente $0, $1,2para llamar en secuencia a los parámetros de la clausura.
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: { $0 > $1 }) print(reversed)
$0 y $1representa los primeros y segundos parámetros de tipo String en la clausura.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Si utiliza abreviaturas de nombres de parámetros en la expresión de clausura, puede omitir su definición en la lista de parámetros de la clausura y el tipo de la abreviatura del nombre del parámetro se infiere a través del tipo de función. La palabra clave in también se puede omitir.
De hecho, hay una manera más corta de escribir la expresión de clausura en el ejemplo anterior.
SwiftString
La definición del operador de comparación de mayor que (>
) implementación de cadena como una función que acepta dosString
parámetros y devuelveBool
valores del tipo.
Y esto coincide consort(_)
El segundo parámetro de la función necesita un tipo de función que coincida.
Por lo tanto, puede simplemente pasar un signo mayor, y Swift puede inferir automáticamente que desea usar la implementación de la función de cadena de signo mayor:
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] var reversed = names.sorted(by: >) print(reversed)
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Una clausura de cola es una expresión de clausura escrita después de los paréntesis de una función, y el lenguaje de programación admite que se la llame como el último parámetro.
func someFunctionThatTakesAClosure(closure: () -> Void) { // Parte del cuerpo de la función } // A continuación se muestra cómo se realiza una llamada a la función sin utilizar una clausura de cola someFunctionThatTakesAClosure({ // Parte del cuerpo de la closure ) // A continuación se muestra cómo se realiza una llamada a la función utilizando una clausura de cola someFunctionThatTakesAClosure() {}} // Parte del cuerpo de la closure }
import Cocoa let names = ["AT", "AE", "D", "S", "BE"] //Closures de cola var reversed = names.sorted() { $0 > $1 } print(reversed)
Después de sort() { $0 > $1} como closure de cola.
以上程序执行输出结果为:
["S", "D", "BE", "AT", "AE"]
Nota:
Si la función solo necesita un parámetro de expresión de closure, incluso puede omitir los paréntesis cuando se utiliza una closure de cola.()
Se omitió.
reversed = names.sorted { $0 > $1 }
La closure puede capturar constantes o variables en el contexto en el que se define.
Incluso si el ámbito original de definición de estas constantes y variables ya no existe, la closure puede referirse y modificar estos valores dentro de la función de closure.
La forma más simple de closure en Swift es la función anidada, es decir, una función definida dentro del cuerpo de otra función.
Las funciones anidadas pueden capturar todos los parámetros y constantes definidas en la función externa.
Ve este ejemplo:
func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor }
Una función makeIncrementor que tiene un parámetro de tipo Int llamado amout, y un parámetro externo llamado forIncremet, lo que significa que debe usar este nombre externo al llamar. El valor de retorno es un()-> Int
de la función.
En el cuerpo de la función, se declaran las variables runningTotal y una función incrementor.
La función incrementor no recibe ningún parámetro, pero accede a las variables runningTotal y amount dentro del cuerpo de la función. Esto se debe a que captura las variables runningTotal y amount que ya existen en el cuerpo de la función que la contiene.
Dado que no se modificó la variable amount, incrementor realmente captura y almacena una copia de esta variable, y esta copia se almacena junto con incrementor.
Por lo tanto, cuando llamamos a esta función, se acumulará:
import Cocoa func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: 10) // 返回的值为10 print(incrementByTen()) // 返回的值为20 print(incrementByTen()) // 返回的值为30 print(incrementByTen())
以上程序执行输出结果为:
10 20 30
En el ejemplo anterior, incrementByTen es una constante, pero estas constantes aún pueden aumentar el valor de las variables capturadas por la closure.
Esto se debe a que tanto las funciones como las closures son tipos de referencia.
No importa si asigna una función/Independientemente de si asigna una closure a una constante o a una variable, en realidad está asignando una constante/El valor de la variable se establece para la función correspondiente/Referencia de closure. En el ejemplo anterior, incrementByTen apunta a una referencia de closure que es una constante, no al contenido de la closure en sí.
这也意味着如果您将闭包赋值给了两个不同的常量/变量,两个值都会指向同一个闭包:
import Cocoa func makeIncrementor(forIncrement amount: Int) -> () -> Int { var runningTotal = 0 func incrementor() -> Int { runningTotal += amount return runningTotal } return incrementor } let incrementByTen = makeIncrementor(forIncrement: 10) // 返回的值为10 incrementByTen() // 返回的值为20 incrementByTen() // 返回的值为30 incrementByTen() // 返回的值为40 incrementByTen() let alsoIncrementByTen = incrementByTen // 返回的值也为50 print(alsoIncrementByTen())
以上程序执行输出结果为:
50