Swift 逃逸和非逃逸闭包
Swift 闭包
与其他编程语言一样,Swift 也支持 Closure。闭包是一个自包含的功能块,可以在代码中传递和使用来执行任何特定任务。它可以赋值给变量,或者作为参数传递给 function。闭包可以捕获其周围上下文中的值,并可以用作 callback 或内联代码。Swift 支持以下类型的闭包:
- Escaping Closure
- Non-Escaping Closure
让我们详细讨论它们。
Swift 中的 Escaping Closures
当一个闭包作为参数传递给 function,但该闭包在 function 返回后被调用时,这种类型的闭包被称为 escaping closure。默认情况下,作为参数传递给 function 的闭包是非逃逸参数,这意味着闭包将在 function 执行期间执行。
要将闭包声明为 escaping closure,我们需要在表示 escaping closure 的参数类型前使用 @escaping 关键字。
语法
以下是 escaping closure 的语法:
func methodname(closure: @escaping() -> Void){
// body
// 调用闭包
closure()
}
示例
演示 escaping closure 的 Swift 程序。
import Foundation
class Operation{
// 接受两个数字和一个 escaping closure 的方法,用于计算它们的乘积
func product(_ x: Int, _ y: Int, productResult: @escaping (Int) -> Void) {
// 激活异步任务
DispatchQueue.global().async {
let output = x * y
// 调用 escaping closure
productResult(output)
}
}
}
// 创建 Operation class 的对象
let obj = Operation()
// 访问方法
obj.product(10, 4) { res in
print("10 * 4 的乘积 = \(res)")
}
// 激活时间流逝
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
// 它将在延迟后执行,模拟异步操作
}
输出
它将产生以下输出:
Product of 10 * 4 = 40
Swift 中的 Non-Escaping Closure
Non-escaping closures 是 Swift 中的默认行为,我们不需要任何特殊标记来表示 non-escaping closures。这种类型的闭包在它们被传递的 function 执行期间执行,一旦 function 执行结束,闭包就不再可用执行。它们不会被存储以供后续执行。
语法
以下是非逃逸闭包的语法:
mutating func methodname(Parameters) -> returntype {
Statement
}
示例
演示 non-escaping closure 的 Swift 程序。
class Operation {
// 接受两个数字和一个 non-escaping closure 的函数,用于计算它们的和
func sum(_ X: Int, _ Y: Int, add: (Int) -> Void) {
let result = X + Y
// 调用 non-escaping closure
add(result)
}
}
// 创建 operation class 的对象
let obj = Operation()
obj.sum(10, 12) { add in
print("和: \(add)")
}
输出
它将产生以下输出:
Sum: 22
Escaping 与 Non-Escaping Closure 的比较
以下是 escaping 和 non-escaping closures 之间的主要区别:
| Escaping Closure | Non-Escaping Closure |
|---|---|
| 它可以存活超过传递它的 function。 | 它在 function 执行期间执行。 |
| 它可以作为 property 存储或赋值给变量。 | 它不能被存储,且不允许在 function 作用域外使用。 |
| 它通常用于异步操作,如网络请求等。 | 它通常用于同步操作,如简单计算等。 |
| 使用 @escaping 关键字创建 escaping closure。 | 它是默认闭包,不需要任何特殊语法。 |