C. Thomas Brittain
C. Thomas Brittain

Reputation: 386

NSTimer not Scheduling in WatchOS2

I'm tying to get a heart throbbing animation to match the heart-rate sampled form HealthKit in WatchOS2. I can't seem to find a way to update the timer interval based upon more recent samples.

After a bit of research, invalidating the timer and rescheduling is the recommended method; but the following bit of code doesn't seem to get the job done.

class InterfaceController: WKInterfaceController {

var timer: NSTimer?


private func updateHeartRate(rate: Int) {
    ...


    heartBeatIntensity = NSTimeInterval(0.0166 * Float(rate))
    print(heartBeatIntensity)

    if let timer = timer {
        timer.invalidate()
    }

    timer = NSTimer.scheduledTimerWithTimeInterval(heartBeatIntensity, target:self, selector: Selector("updatesByTimer"), userInfo: nil, repeats: true)
}

Upvotes: 1

Views: 548

Answers (3)

C. Thomas Brittain
C. Thomas Brittain

Reputation: 386

Well, here it is, but it's pretty wonky.

The timer is dispatched,

    dispatch_async(dispatch_get_main_queue()){
        self.heartBeatIntensity = NSTimeInterval(60 / Float(rate))
        if let timer = self.timer {
            timer.invalidate()
        }
        self.timer = NSTimer.scheduledTimerWithTimeInterval(self.heartBeatIntensity, target:self, selector: Selector("updatesByTimer"), userInfo: nil, repeats: true)
    }

Then, I had to include an extension to WKInterfaceController for animateWithDuration to add a completion block (SO post where I found the code). After which, I ended up with this,

func updatesByTimer(){
    WKInterfaceDevice.currentDevice().playHaptic(.Click)

    animateWithDuration(heartBeatIntensity/2,
        animations:
        {
            self.beatingHeart.setHeight(55.0)
            self.beatingHeart.setWidth(55.0)
        },
        completion: {
            self.animateWithDuration(self.heartBeatIntensity/2, animations: {
                self.beatingHeart.setHeight(85.0)
                self.beatingHeart.setWidth(85.0)
            })
        })
}

Does this seem right? It had the desired effect, except for stick when the new sample is being taken.

Upvotes: 0

hiro_kimu
hiro_kimu

Reputation: 116

According to the watchOS 2.0 document, HKAnchoredObjectQuery's updateHandler is called from the background thread.

the query executes this update handler on a background queue.

Try this.

private func updateHeartRate(rate: Int) {
    ...

    dispatch_async(dispatch_get_main_queue()) {
        //your code
    }
}

Upvotes: 3

Philip
Philip

Reputation: 2285

This works for me. I am defining a variable

NSTimer *timer;

And when I want to start it:

timer = [NSTimer scheduledTimerWithTimeInterval:60.0f target:self selector:@selector(timeUpdated) userInfo:nil repeats:YES];

Then I am invalidating it

- (void)didDeactivate {
    // This method is called when watch view controller is no longer visible
    [super didDeactivate];

    [timer invalidate];
}

Have you tried to dispatch to the main queue when you want to start the timer?

Upvotes: 2

Related Questions