Swift中,(()->()) 和@escaping () -> Void 有什么区别?

In Swift, What is the difference between (()->()) and @escaping () -> Void?

(()->()) 和@escaping () -> Void 有什么区别?

func foo(_ completion: (() -> ()) { }

func boo(_ completion: @escaping () -> Void) { }

快速摘录


转义闭包
当闭包作为参数传递给函数时,闭包被称为转义函数,但在函数 returns 之后被调用。当你声明一个将闭包作为其参数之一的函数时,你可以在参数类型之前写 @escaping 来表示允许闭包转义。

闭包逃逸的一种方法是将其存储在函数外部定义的变量中。例如,许多启动异步操作的函数都将闭包参数作为完成处理程序。函数 returns 开始操作后,但直到操作完成后才调用闭包——闭包需要转义,以便稍后调用。例如:

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure(_:) 函数将闭包作为参数并将其添加到在函数外部声明的数组中。如果你没有用 @escaping 标记这个函数的参数,你会得到一个编译时错误。”

“let alsoIncrementByTen = incrementByTen
alsoIncrementByTen()
// returns a value of 50

incrementByTen()
// returns a value of 60

上面的例子说明调用alsoIncrementByTen和调用incrementByTen是一样的。因为它们都引用同一个闭包,所以它们都递增 return 相同的 运行 总数。

转义闭包 当闭包作为参数传递给函数时,闭包被称为转义函数,但在函数 returns 之后被调用。当你声明一个将闭包作为其参数之一的函数时,你可以在参数类型之前写 @escaping 来表示允许闭包转义。

闭包逃逸的一种方法是将其存储在函数外部定义的变量中。例如,许多启动异步操作的函数都将闭包参数作为完成处理程序。函数 returns 开始操作后,但直到操作完成后才调用闭包——闭包需要转义,以便稍后调用。例如:

var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
    completionHandlers.append(completionHandler)
}

someFunctionWithEscapingClosure(_:) 函数将闭包作为参数并将其添加到声明的数组中[...]”


摘自:Apple Inc.“Swift 编程语言 (Swift 5.2)。”苹果图书。 https://books.apple.com/us/book/the-swift-programming-language-swift-5-2/id881256329


换句话说,@escaping 闭包需要使用 self,如果你试图引用当前对象中的方法。即 SKActions 的完成闭包就是一个很好的例子。

并且非转义闭包不需要使用 self.因为它们不用于引用对象。