【问题标题】:In Swift, What is the difference between (()->()) and @escaping () -> Void?在 Swift 中,(()->()) 和 @escaping () -> Void 有什么区别?
【发布时间】:2020-04-29 00:35:57
【问题描述】:

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

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

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

【问题讨论】:

标签: swift escaping closures void swift5


【解决方案1】:

快速摘录


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

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

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 是一样的。因为它们都引用同一个闭包,所以它们都递增并返回相同的运行总计。

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

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

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。即 SKAction 的完成闭包就是一个很好的例子。

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

【讨论】:

  • "但在函数返回后调用。"应该是“可以”而不是“是”。没有必要调用转义闭包,它完全有可能被丢弃
猜你喜欢
  • 2017-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-07-16
  • 2017-12-05
  • 2012-08-09
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多