我有一个inout
参数的函数:enabled: Bool
我引用的对象(我知道inout
在技术上不是引用...),使用此方法设置是UIViewController
上的存储属性
var enabled = false
我有多个布尔值触发不同的东西,我想用一种方法来设置它们。
所以我称之为方法:
self.determineEnabled(&self.enabled)
下面是代码,我用评论来解释发生的事情
代码:
func determineEnabled(inout enabled: Bool) {
if enabled == false {
enabled = true
//self.enabled equals true now. This works. Its not in a closure...
} else {
let delete = UIAlertAction(title: "Disable", style: .Destructive, handler: { (action) -> Void in
enabled = false
print(self.enabled)
//This doesn't work. the inout variable equals FALSE
//self.enabled equals true
//If I set self.enabled = false.. Then it works, but I'm using a method because my app could have dozens of these enabled bools on this view controller.
let alertController = UIAlertController(title: "Change Bool", message: "", preferredStyle: UIAlertControllerStyle.Alert)
alertController.addAction(delete)
self.presentViewController(alertController, animated: true, completion: nil)
}
}
我的应用程序显然比这块代码更复杂,但我可以验证这个代码中存在的这个问题。
我说实话,我并不像我想的那样彻底了解封口..
但是,如果我可以使用self.enabled
来正确更改启用的值,那么什么阻止swift更改设置启用输入的变量?
更新:
以下是专门提及我的问题的文档链接: https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Declarations.html#//apple_ref/doc/uid/TP40014097-CH34-ID545
"闭包或嵌套函数末尾没有复制。这意味着如果在函数返回后调用闭包,则闭包对输入输出参数所做的任何更改都不会复制回原始参数。"
关于这个主题的迅速演变: https://github.com/apple/swift-evolution/blob/master/proposals/0035-limit-inout-capture.md
答案 0 :(得分:3)
在Swift中,函数是闭包。闭包捕获状态。当我们遇到包含代码print(self.enabled)
的匿名函数时,self.enabled
为true
。我们知道,因为如果不是,我们就不会在这里(我们处于条件的第一翼,if enabled == false
)。因此,当print(self.enabled)
稍后实际执行时,它将打印true
,因为这是捕获其值时的状态。
答案 1 :(得分:2)
你自己在问题中说过了;
我知道inout在技术上并不是一个参考
来自Apple Swift的书
输入输出参数的值在中传递给函数, 由函数修改并传回函数的 out 替换原始值。
您正在修改闭包中的值,该闭包在用户与警报交互后执行一段时间。此时determineEnabled
已经返回并存储了inout
参数的值。
如果inout
参数是引用,就像C风格的指针一样,那么enabled
将指向存储self.enabled
的一块内存当在闭包中修改值时,self.enabled
将被修改。
如果您创建一个带有布尔属性的简单类,然后将此类的实例传递给determineEnabled
函数(不使用inout
),则可以看到这是如何工作的。由于对象是通过引用传递,因此在使用相同对象引用的任何地方,对闭包中对象属性的后续更新都是可见的;