非逃逸闭包的实际用途是什么?

4

如果一个函数可以自行返回值,为什么需要调用非逃逸闭包来返回值呢?考虑以下示例:

 func add(a: Int, b: Int, completion: (Int) -> ()) {
        let addition = a + b
        completion(addition)
 }

你可以将闭包传递给那些不知道如何调用该函数的人。 - Thilo
在你的例子中,也许add的调用者(我们称之为foo)不知道completion的作用。foo只是从其他地方(作为闭包)接收到它。而foo的调用者知道完成回调应该做什么,但没有直接调用add的必要。也许像这样:foo(listOfManyNumbersToFold, printResultCompletion) - Thilo
3个回答

2
例如,某些原因导致参数ab必须是正数。有三种方法可以解决这个问题:
1)您可以在调用add函数的函数中添加此检查。如果这样做,每次在调用add之前都需要重复此代码。由于代码重复,这不是一个好主意;
2)您可以在add方法中添加此检查并将错误返回给一个闭包。在任何闭包中,即使您不想执行任何代码,也必须处理此错误。因此,这也不是一个好主意;
3)您可以在add方法中添加此检查,并返回一个布尔值来显示参数的正确性。如果参数正确,则计算结果并像以下代码一样调用闭包:
func add(a: Int, b: Int, completion: (Int) -> ()) -> Bool {
    guard a > 0, b > 0 else {
      return false
    }

    let addition = a + b
    completion(addition)

    return true
}

if !add(a: someA, b: someB, completion: {sum in print(sum)}) {
  print("Wrong numbers!")
}

1

闭包的常见用例包括:

  1. 异步调用;网络。

  2. 将函数存储为变量;考虑操作和提供的回调。

  3. 在调度队列上安排任务。

如果有一个需要花费一些时间才能完成工作并返回结果的过程,那么在这些情况下,闭包是最好的选择。

非逃逸闭包

非逃逸闭包具有非常清晰的生命周期,并因此成为 Swift 3 中默认的闭包类型。非逃逸闭包很简单:它被传递到一个函数(或其他包含范围)中,该函数/范围执行该闭包,然后函数返回。在调用函数的主体返回后,闭包无法返回或完成执行。由于这个事实,编译器能够优化非逃逸闭包而不是逃逸闭包。

默认闭包行为(非逃逸)

假设有一个带有闭包的简单函数,像这样:

func macICanBuy(budget: Int, closure: (String) -> Void) {
  print("checking budget...")

  closure("Mcdonalds' Big Mac")

  print("macICanBuy finished execution")
}

override func viewDidLoad(){
  macICanBuy(budget: 100, closure: { mac in
    print("I can afford a \(mac)")
  })
}

// output: 
// checking budget...
// I can afford a Mcdonalds' Big Mac
// macICanBuy finished execution

在应用程序执行macICanBuy函数之前,它会将传递的参数(预算和闭包)加载到手机内存(RAM)中,以便函数可以使用这些数据。
在应用程序完成执行macICanBuy函数后,应用程序不再需要预算和闭包数据,因此它们将从内存中删除。闭包数据在函数执行完毕后未能逃脱被从内存中删除,因此被称为“非逃逸”闭包。
以上内容参考自:

https://fluffy.es/what-is-escaping-closure/


是的,你说得对。但我的问题是,如果我们考虑上面的例子,我们可以简单地从函数中返回一个值,那么为什么有人会使用非逃逸闭包?在什么情况下我们应该使用非逃逸闭包而不是从函数中返回值? - Pankaj Battise
@PankajBattise 这对你有帮助吗? - Daljeet

0
基本上,具有返回值的函数和非逃逸闭包之间没有太大的区别。 这更多是关于语法选择。
主要用例是将它们用作异步调用的逃逸闭包。 然而,如果你想在另一个内部作用域中使用返回值,那么非逃逸闭包就很合适。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接