How to update variable based on an external event in Swift?

137 Views Asked by At

I am using a Particle Core to get the temperature from my room. The temperature is accessed through the cloud, which is being constantly updated in a variable. This is how I access the variable and display it:

func updateTemp(){
    let seconds = 3.0
    let delay = seconds * Double(NSEC_PER_SEC)  // nanoseconds per seconds
    let dispatchTime = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))

    dispatch_after(dispatchTime, dispatch_get_main_queue(), {
        self.myPhoton?.getVariable("tempF", completion: { (result:AnyObject!, error:NSError!) -> Void in
            if let _ = error {
                print("Failed reading temperature from device")
            }
            else {
                if let larry = result as? Int {
                    self.temp.text="\(larry)˚"
                    self.truth++ //Once a value has been found, update the count.
                }
            }
        })
    })   
}

override func viewDidLoad() {

    sparkStart()

}

override func viewDidLayoutSubviews() {
    updateTemp()

    NSTimer.scheduledTimerWithTimeInterval(100.0, target: self, selector: "updateTemp", userInfo: nil, repeats: true) //Gaurantees that the app is updated every 100 seconds. That way we have a fresh temperature often.

    //Stop the spinning once a value has been found
    if truth == 1{
        activity.stopAnimating()
        activity.removeFromSuperview()
    } 
}

Since this is my Particle Core detecting the temperature from environment, the temperature variable is constantly changing. However, when I use NSTimer, the code does not get updated in the time specified. Instead, it begins by updating based on the specified time, but then the time starts decreases exponentially and the variable is updated every 0.001 seconds or so. Any thoughts?

1

There are 1 best solutions below

0
On

Im assuming what we see is not the full code. In your viewDidLayoutSubviews function, you call updateTemp twice. Once explicitly and once via timer callback.

Your updateTemp function schedules the network call in the main run loop, that's where the timer is also running. The dispatch_after function queues the execution of the readout updates one after the other. I am now assuming, that something in your display code causes repeated triggers of viewDidLayoutSubviews, each of which schedules two new updates etc. Even if the assumption is false (there are a couple of other possibilities due to network code being slow and the timer also running in the main run loop), I am guessing if you drop the explicit call to updateTemp you'll lose the "exponential" and should be fine.

In general, as the web call is largely asynchronous, you could just use the timer and call your sensor directly or if you feel GCD has an important performance advantage switch to dispatch_async and apply for the next available queue with each call via calling dispatch_get_global_queue