所以这段代码是一个逃避关闭,我确实理解它的@escaping是必需的,因为该函数会转义并附加或更改完成处理程序。
var completionHandlers: [() -> Void] = []
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
func someFunctionWithNonescapingClosure(closure: () -> Void) {
closure()
}
class SomeClass {
var x = 10
func doSomething() {
someFunctionWithEscapingClosure { self.x = 100 }
someFunctionWithNonescapingClosure { x = 200 }
}
}
let instance = SomeClass()
instance.doSomething()
print(instance.x)
// Prints "200"
completionHandlers.first?()
print(instance.x)
// Prints "100”
这个简单的代码并不要求将值类型标记为已转义,即使它更改了变量x。
var x: Int = 0
func x (y: Int) {
x += y
}
x (y: 7)
print (x)
这让我感到困惑,因为我不明白为什么在第二个代码中可以隐式评估self,但是需要一个转义关闭self(如果它被调用)。
答案 0 :(得分:1)
我确实理解它的@escaping是必需的,因为该函数会转义并附加或更改完成处理程序。
从这句话中你并不完全清楚你明白@escaping
的含义。这意味着此函数参数将存储而不是立即执行并丢弃。
这就是你的第一个例子中发生的事情:我们交给() -> Void
而不是仅执行它,我们将它附加到持久数组。
在你的第二个例子中,没有函数参数(只是一个低Int),所以问题永远不会出现。
原因为什么函数参数出现的问题是函数是闭包,所以当函数存储时,其环境中的其他东西可以被存储。这可能会产生意想不到的后果,因此您必须通过说@escaping
来承认您已经意识到这一点。