Swift 闭包怎么区分 Escaping 和 Non-escaping?

文章导读
Previous Quiz Next Swift 闭包 与其他编程语言一样,Swift 也支持 Closure。闭包是一个自包含的功能块,可以在代码中传递和使用来执行任何特定任务。它可以赋值给变量,或者作为参数传递给 function。闭包可以捕获其周围上下文中的值,并可以
📋 目录
  1. A Swift 闭包
  2. B Swift 中的 Escaping Closures
  3. C Swift 中的 Non-Escaping Closure
  4. D Escaping 与 Non-Escaping Closure 的比较
A A

Swift 逃逸和非逃逸闭包



Previous
Quiz
Next

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。 它是默认闭包,不需要任何特殊语法。