为什么不值类型需要@escaping或显式自我而不是转义闭包?

时间:2017-08-27 00:19:29

标签: swift closures

所以这段代码是一个逃避关闭,我确实理解它的@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(如果它被调用)。

1 个答案:

答案 0 :(得分:1)

  

我确实理解它的@escaping是必需的,因为该函数会转义并附加或更改完成处理程序。

从这句话中你并不完全清楚你明白@escaping的含义。这意味着此函数参数存储而不是立即执行并丢弃。

这就是你的第一个例子中发生的事情:我们交给() -> Void而不是仅执行它,我们将它附加到持久数组。

在你的第二个例子中,没有函数参数(只是一个低Int),所以问题永远不会出现。

原因为什么函数参数出现的问题是函数是闭包,所以当函数存储时,其环境中的其他东西可以被存储。这可能会产生意想不到的后果,因此您必须通过说@escaping来承认您已经意识到这一点。