Swift para desarrollo de iOS (7) -Cierre

versión

Xcode 11.0
Swift 5.1

Definición y uso de cierres

1. Concepto Un
cierre es un bloque de código de función autónomo que se puede pasar y utilizar en el código. Los cierres en Swift son similares a los bloques en C y Objective-C, así como a las funciones anónimas (Lambdas) en otros lenguajes de programación.
De hecho, las funciones globales y las funciones anidadas son en realidad cierres especiales. Las diferencias son las siguientes:

  • Una función global es un cierre que tiene un nombre pero no captura ningún valor
  • Una función anidada es un cierre que tiene un nombre y puede capturar el valor de su dominio de función circundante.
  • Una expresión de cierre es un cierre anónimo escrito con una sintaxis ligera que puede capturar la variable o el valor constante en su contexto.

El valor de captura se introduce más adelante en el artículo.

2. Definición (expresión)
Antes de discutir la definición de cierres, repasemos las funciones globales y las funciones anidadas.

// 函数表达式
func 函数名(参数列表) -> 返回类型 {
    
    
    // 函数体
}

Como la expresión anterior, definida en el dominio global se llama función global, y definida en el cuerpo de una función se llama función anidada.
Veamos cómo se define la expresión de un cierre:

// 闭包表达式
{
    
     (参数列表) -> 返回值类型 in
    // 闭包体 (可执行代码语句)
}

Comparando las expresiones de funciones y cierres, existen las siguientes diferencias:

  • Las funciones tienen nombre, los cierres no tienen nombre.
  • Las llaves de la función son después del tipo de retorno y envuelven el cuerpo de la función; las llaves de cierre son todos los parámetros / valores de retorno / en la palabra clave / cuerpo de cierre.
  • El cuerpo del cierre del cierre está en el área detrás de la palabra clave in.
  • Los parámetros de expresión de cierre pueden ser parámetros de entrada y salida, pero no se pueden establecer valores predeterminados.

3. Utilice (instancia)
instancia de cierre:

// 定义一个闭包, 并赋值给一个常量 maxValue
// 或者说定义一个常量 maxValue 指向后面这个闭包
let maxValue: (Int, Int) -> Int = {
    
     (x: Int, y: Int) -> Int in
    return x > y ? x : y
}

// 使用 maxValue 来调用闭包
print(maxValue(11, 22))
// 打印 22

4. Inferencia de contexto y
retorno implícito Dado que Swift puede inferir los tipos de parámetro y valor de retorno, y el cierre de expresión de una sola línea puede devolver implícitamente el resultado de la expresión de una sola línea al omitir la palabra clave de retorno, el código anterior se puede abreviar como:

// 定义
let maxValue: (Int, Int) -> Int = {
    
     x, y in x > y ? x : y }

// 使用 maxValue 来调用闭包
print(maxValue(11, 22))
// 打印 22

5. Abreviatura del nombre del parámetro
Swift proporciona automáticamente la función de abreviatura del nombre del parámetro para cierres en línea. Puede llamar directamente los parámetros del cierre en secuencia mediante $ 0, $ 1, $ 2, etc.

// 参数名称缩写
// 定义一个闭包, 并赋值给一个常量 add
let add: (Int, Int) -> Int = {
    
     $0 + $1 }

// 使用 add 来调用闭包
print(add(11, 22))
// 打印 33

6. Captura de valores Al
igual que las funciones anidadas, los cierres también pueden capturar valores externos Los
cierres pueden capturar constantes o variables en el contexto en el que se definen. Incluso si el alcance original de la definición de estas constantes y variables ya no existe, el cierre aún puede hacer referencia y modificar estos valores en el cuerpo de la función de cierre.

// 捕获值
var aa = 10
let setValue: () -> () = {
    
    
    aa = 88
}

// 调用闭包 (无参数无返回值)
setValue()
print(aa)
// 打印 88

Cierre como parámetro de función

Defina una función de suma, pase tres parámetros: aClosure: (Int, Int) -> Int y x: Int e y: Int , el valor de retorno es el tipo Int. El cierre también pasa dos parámetros Int y devuelve un valor Int, Devuelve el valor de retorno del cierre en el cuerpo de la función. El
código es el siguiente:

// 定义函数
func doAdd(aClosure: (Int, Int) -> Int, x: Int, y: Int) -> Int {
    
    
    return aClosure(x, y)   // 传入函数的x/y值, 返回闭包的返回值
}

// 调用函数, 在这里写闭包体
let ret = doAdd(aClosure: {
    
     (aa, bb) -> Int in
    return aa + bb          // 闭包体部分: 接收函数的x/y值进行相加
}, x: 10, y: 15)

print(ret)
// 打印 25

Cierre final

En el ejemplo anterior, el cierre se pasa como un parámetro en la función, que no es muy legible. Vamos a introducir el cierre final.
Como sugiere el nombre, el cierre final es el cierre al final. Además, el cierre final es una expresión de cierre escrita después del paréntesis de la función, y la función admite llamarlo como último parámetro.
La función de adición anterior utiliza cierres finales para mejorar la legibilidad:

// 定义函数 (三个形参:x,y和闭包aClosure; 一个返回值Int类型)
func doAdd(x: Int, y: Int, aClosure: (Int, Int) -> Int) -> Int {
    
    
    return aClosure(x, y)
}

// 调用函数, 此时闭包体已经移到()外边
let ret = doAdd(x: 10, y: 20) {
    
     (aa, bb) -> Int in
    return aa + bb
}

print(ret)
// 打印 30

Tenga en cuenta
que el cierre debe utilizarse como último parámetro de la función para convertirse en un cierre final.

Cierre de escape

Supongamos que pasamos un cierre a la función como parámetro y luego llamamos al cierre de forma asincrónica:

import Foundation

// 定义函数
func doNothing(aClosure: () -> ()) {
    
    
    
    DispatchQueue.global().async {
    
    
        aClosure()      // 异步调用闭包
    }
}

// 调用函数
doNothing {
    
    
    print("调用了闭包")
}

// 编译报错

En este momento, se informará un error al compilar. Debido a que el código que llama al cierre de forma asincrónica se ejecuta después de que regresa la función doNothing, y el cierre como una variable local se libera después de que la función regresa, la llamada informará un error en este El cierre de escape puede resolver este problema.

Cuando se pasa un cierre como parámetro a una función, pero el cierre se ejecuta después de que la función regresa, llamamos al cierre escape de la función. Cuando define una función que acepta un cierre como parámetro, puede marcar @escaping antes del nombre del parámetro para indicar que el cierre puede "escapar" de la función.

Mirando el ejemplo de hace un momento, se ejecuta correctamente:

import Foundation

// 定义函数
func doNothing(aClosure: @escaping () -> ()) {
    
    
    
    DispatchQueue.global().async {
    
    
        aClosure()      // 异步调用闭包
    }
}

// 调用函数
doNothing {
    
    
    print("调用了闭包")
}

// 打印 调用了闭包

Tenga en cuenta que
marcar un cierre como @escaping significa que debe hacer referencia explícitamente a sí mismo en el cierre.

Supongo que te gusta

Origin blog.csdn.net/u012078168/article/details/103728428
Recomendado
Clasificación