0

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.

Philip Feldmann
  • 7,887
  • 6
  • 41
  • 65
  • Thanks for your comment. Does that mean it is not possible at all to measure the heartrate while the screen of the watch is black, even though the app is in the front? I honestly didn't expect that, how are you supposed to write reliable workout apps for the apple watch then? Is there any kind of workaround you could suggest? – Philip Feldmann Apr 18 '16 at 17:20
  • 1
    Correct, it is not possible to write a watchOS 2 app that reads the user's heart rate in real time while the watch's screen is off. There is no workaround for this - watchOS apps do not get to run in the background to limit battery consumption. When the screen turns on, however, the heart rate measurements that were taken while the screen was off will become available to your app (as you have probably already noticed with updateHandler of your HKAnchoredObjectQuery). – Allan Apr 18 '16 at 17:49
  • Too bad then. Thank you very much! – Philip Feldmann Apr 18 '16 at 17:52

0 Answers0