I want to use the Healthkit API on my apple-watch to meassure my heartrate while sleeping in a certain interval.
For this purpose I've implemented a simple SleepSessionManager class which takes care of all the setup for a HKWorkout
. Its delegate is the InterfaceController
, which also owns the instance of the class. I'm updating the heartrate with a streaming Query in this method in the SleepSessionManager:
func createHeartRateStreamingQuery(workoutStartDate: NSDate) -> HKQuery? {
guard let quantityType = HKObjectType.quantityTypeForIdentifier(HKQuantityTypeIdentifierHeartRate) else { return nil }
let heartRateQuery = HKAnchoredObjectQuery(type: quantityType, predicate: nil, anchor: anchor, limit: Int(HKObjectQueryNoLimit)) { (query, sampleObjects, deletedObjects, newAnchor, error) -> Void in
guard let newAnchor = newAnchor else {return}
self.anchor = newAnchor
self.delegate.heartRateDidChange(sampleObjects)
}
heartRateQuery.updateHandler = {(query, samples, deleteObjects, newAnchor, error) -> Void in
self.anchor = newAnchor!
NSLog("About to update Heartrate")
// InterfaceController
self.delegate.heartRateDidChange(samples)
}
// Will get executed by healthStore
return heartRateQuery
}
and then updating the View in my InterfaceController this way:
func heartRateDidChange(samples: [HKSample]?) {
NSLog("HeartRate did change")
guard let heartRateSamples = samples as? [HKQuantitySample] else {return}
dispatch_async(dispatch_get_main_queue()) {
guard let sample = heartRateSamples.first else{return}
let value = sample.quantity.doubleValueForUnit(self.sleepSessionManager!.heartRateUnit)
self.label.setText(String(UInt16(value)))
if UInt16(value) > 80 {
// Feedback when heartRate is more than 80 bpm
WKInterfaceDevice.currentDevice().playHaptic(.Notification)
}
}
}
This works fine as long as the Interface is awake, when the Watch goes back to sleep however, it wont call the heartRateDidChange function any longer, until it awakes again (none of the NSlogs is printed in the console).
I get that I can't call methods on the InterfaceController while it's asleep, but shouldn't the updateHandler run anyway? If you look at the watch, the Heartrate-Sensor is also still active.
Since this is an API dedicated for workouts, I guess that there has to be a way of updating my heartrate even if the watch is asleep, else the user had to look at his watch for the entire duration of the workout to measure all the data.