为什么从闭包返回的变量总是落后一步

时间:2015-06-16 23:33:28

标签: ios swift closures

在以下代码中,闭包访问REST API以调用嵌入式uC上的函数,然后从uC读取值。问题是返回到变量的值"结果"下面,总是落后一步。这意味着,当我打开LED并询问光传感器发出的光的值时,我应该得到灯亮时的预期值。但我不是。我得到了关灯的价值。如果我然后关闭LED,我会得到灯的值。我把设备放在我面前,这样我就能在视觉上确认状态。

我的问题是,关闭行为导致结果值落后一步是什么,并且,有没有办法获得当前值,而不是之前的值?

@IBAction func lightOn(sender: AnyObject) {
    let funcArgs = [1]
    myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in
        if (error == nil) {
            self.lightStateLabel.text = "LED is on"
        }
    }
    myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in
        if let e = error {
            self.getLightLabel.text = "Failed reading light"
        }
        else {
            if let res = result as? Float {
                self.getLightLabel.text = "Light level is \(res) lumens"
            }
        }
    })



}


@IBAction func lightOff(sender: AnyObject) {
    let funcArgs = [0]
    myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in
        if (error == nil) {
            self.lightStateLabel.text = "LED is off"
        }
    }
    myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in
        if let e = error {
            self.getLightLabel.text = "Failed reading light"
        }
        else {
            if let res = result as? Float {
                self.getLightLabel.text = "Light level is \(res) lumens"
            }
        }
    })

}

2 个答案:

答案 0 :(得分:1)

我要猜一猜。

callFunction使用REST API。所以它是异步的。

getVariable使用REST API并且也是异步的,或者使用上一次REST调用返回的本地状态记录。

您最多创造了一种竞争条件,callFunction可能无法在getVariable之前完成。在最坏的情况下,它基本上保证不会采取合理的并发控制。

解决方案:在getVariable完成之前,请勿致电callFunction

答案 1 :(得分:1)

您正在进行的Web请求是异步发生的。因此,您检索的值可能尚未更新。尝试在callFunction的完成处理程序中将您的调用嵌套到@IBAction func lightOn(sender: AnyObject) { let funcArgs = [1] myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in if (error == nil) { self.lightStateLabel.text = "LED is on" } self.myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in if let e = error { self.getLightLabel.text = "Failed reading light" } else { if let res = result as? Float { self.getLightLabel.text = "Light level is \(res) lumens" } } }) } } @IBAction func lightOff(sender: AnyObject) { let funcArgs = [0] myPhoton!.callFunction("lightLed0", withArguments: funcArgs) { (resultCode : NSNumber!, error : NSError!) -> Void in if (error == nil) { self.lightStateLabel.text = "LED is off" } self.myPhoton!.getVariable("Light", completion: { (result:AnyObject!, error:NSError!) -> Void in if let e = error { self.getLightLabel.text = "Failed reading light" } else { if let res = result as? Float { self.getLightLabel.text = "Light level is \(res) lumens" } } }) } } 。这样的事情可以奏效:

callFunction

正如您的代码当前,在调用getVariable的那一刻,代码将跳过闭包(因为它是异步的)并继续调用callFunction的路径。在getVariable请求完成时,@media (max-width: 480px) { ... }已经检索到过时的信息。