Reputation: 386
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
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
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
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