请考虑以下代码:
func foo(inout success: Bool) -> (()->()) {
return { _ in
success = true
print (success)
}
}
var success = false
let closure = foo(&success)
closure() //prints "true"
print(success) //prints "false"
Run Code Online (Sandbox Code Playgroud)
封闭似乎创造了一个成功的副本,并没有改变原来的.为什么会这样?我曾假设闭包会指向原始,因为我们传递的是inout变量.
有道理,这不会更新您的success变量,因为您的inout参数是的参数foo,而不是闭包本身的参数。如果inout将参数设置为闭包的参数,则会得到所需的行为:
var success = false
let closure = { (inout flag: Bool) -> () in
flag = true
print(flag)
}
closure(&success) //prints "true"
print(success) //prints "true"
Run Code Online (Sandbox Code Playgroud)
只要您将inout参数保留为闭包的参数,此模式也可以与该函数一起使用:
func foo() -> ((inout Bool)->()) {
return { flag in
flag = true
print (flag)
}
}
var success = false
let closure = foo()
closure(&success) //prints "true"
print(success) //prints "true"
Run Code Online (Sandbox Code Playgroud)
如果使用引用类型,您还将获得所需的行为:
class BooleanClass: CustomStringConvertible {
var value: Bool
init(value: Bool) {
self.value = value
}
var description: String { return "\(value)" }
}
func foo(flag: BooleanClass) -> (()->()) {
return {
flag.value = true
print (flag)
}
}
let success = BooleanClass(value: false)
let closure = foo(success)
closure() //prints "true"
print(success) //prints "true"
Run Code Online (Sandbox Code Playgroud)
这似乎被Swift Evolution提案0035所涵盖,并被视为一个错误.
该文档inout将函数的参数称为" 当被调用者返回时写回参数的卷影副本 ".这似乎意味着实质上存在一个success在执行上下文中命名的临时变量foo().然后,success仅在foo()返回时将该temp的值放入外部.
因为在你的情况下foo(),闭包在foo()返回时没有运行,所以"影子副本"的值没有改变.外部success保持其价值.
重要的是闭包已经捕获了阴影副本,而不是success你期望的外部.因此,当闭包最终运行时,该变量的值确实会发生变化,但它不再与原始外部有任何连接success.
该提案使用此代码段演示:
Run Code Online (Sandbox Code Playgroud)func captureAndEscape(inout x: Int) -> () -> Void { let closure = { x += 1 } closure() return closure } var x = 22 let closure = captureAndEscape(&x) print(x) // => 23 closure() print("still \(x)") // => still 23
| 归档时间: |
|
| 查看次数: |
2861 次 |
| 最近记录: |