如果一个函数可以自行返回值,为什么需要调用非逃逸闭包来返回值呢?考虑以下示例:
func add(a: Int, b: Int, completion: (Int) -> ()) {
let addition = a + b
completion(addition)
}
a
和b
必须是正数。有三种方法可以解决这个问题:add
函数的函数中添加此检查。如果这样做,每次在调用add
之前都需要重复此代码。由于代码重复,这不是一个好主意;add
方法中添加此检查并将错误返回给一个闭包。在任何闭包中,即使您不想执行任何代码,也必须处理此错误。因此,这也不是一个好主意;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!")
}
闭包的常见用例包括:
异步调用;网络。
将函数存储为变量;考虑操作和提供的回调。
在调度队列上安排任务。
如果有一个需要花费一些时间才能完成工作并返回结果的过程,那么在这些情况下,闭包是最好的选择。
非逃逸闭包
非逃逸闭包具有非常清晰的生命周期,并因此成为 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
add
的调用者(我们称之为foo
)不知道completion
的作用。foo
只是从其他地方(作为闭包)接收到它。而foo
的调用者知道完成回调应该做什么,但没有直接调用add
的必要。也许像这样:foo(listOfManyNumbersToFold, printResultCompletion)
。 - Thilo