在UIAlertAction中设置的Inout变量不会改变值

时间:2016-03-16 02:48:22

标签: ios swift closures

我有一个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

2 个答案:

答案 0 :(得分:3)

在Swift中,函数是闭包。闭包捕获状态。当我们遇到包含代码print(self.enabled)的匿名函数时,self.enabledtrue。我们知道,因为如果不是,我们就不会在这里(我们处于条件的第一翼,if enabled == false)。因此,当print(self.enabled)稍后实际执行时,它将打印true,因为这是捕获其值时的状态。

答案 1 :(得分:2)

你自己在问题中说过了;

  

我知道inout在技术上并不是一个参考

来自Apple Swift的书

  

输入输出参数的值中传递给函数,   由函数修改并传回函数的 out   替换原始值。

您正在修改闭包中的值,该闭包在用户与警报交互后执行一段时间。此时determineEnabled已经返回并存储了inout参数的值。

如果inout参数引用,就像C风格的指针一样,那么enabled将指向存储self.enabled的一块内存当在闭包中修改值时,self.enabled将被修改。

如果您创建一个带有布尔属性的简单类,然后将此类的实例传递给determineEnabled函数(不使用inout),则可以看到这是如何工作的。由于对象通过引用传递,因此在使用相同对象引用的任何地方,对闭包中对象属性的后续更新都是可见的;