I have created a session in Watch and updating Heart Rate Data in Health Kit. Now, I want to Display the current Heart Rate in my iPhone Screen. Watch sensor update the Heart Rate Data in Health kit BUT iPhone Application in NOT able to Fetch Real-Time Data from the Health kit. I have tested out below TWO scenarios. I have also recalled this method/function using timer BUT it is not getting real-time data.
Note: When I open Health App and Re-open my application then It will automatically refresh the data. If my application continuously in foreground then below code not refreshing latest data from the health kit
1. Tried to get Real Time Heart Rate Data using HKSampleQuery
let calendar = NSCalendar.current
let components = calendar.dateComponents([.year, .month, .day], from: Date())
let startDate : NSDate = calendar.date(from: components)! as NSDate
let endDate : Date = calendar.date(byAdding: Calendar.Component.day, value: 1, to: startDate as Date)!
let predicate = HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options:[])
//descriptor
let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierEndDate, ascending: false)]
self.heartRateQuery = HKSampleQuery(sampleType: self.heartRateType, predicate: predicate, limit: 1, sortDescriptors: sortDescriptors, resultsHandler: { (query:HKSampleQuery, results:[HKSample]?, error:Error?) in
guard error == nil else { print("error in getting data"); return }
self.collectCurrentHeartRateSample(currentSampleTyple: results)
})
self.healthStore.execute(self.heartRateQuery!)
2. Tried to get Real Time Heart Rate Data using HKAnchoredObjectQuery
let sampleType : HKSampleType = HKObjectType.quantityType(forIdentifier: HKQuantityTypeIdentifier.heartRate)!
let predicate : NSPredicate = HKQuery.predicateForSamples(withStart: startDate as Date, end: endDate, options: [])
let anchor: HKQueryAnchor = HKQueryAnchor(fromValue: 0)
let anchoredQuery = HKAnchoredObjectQuery(type: sampleType, predicate: predicate, anchor: anchor, limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, anchor, error ) in
self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
}
anchoredQuery.updateHandler = { (query, samples, deletedObjects, anchor, error) -> Void in
self.collectCurrentHeartRateSample(currentSampleTyple: samples!, deleted: deletedObjects!)
}
self.healthStore.execute(anchoredQuery)
=============================================
Parsed the Data
func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?, deleted :
[HKDeletedObject]?){
// func collectCurrentHeartRateSample(currentSampleTyple : [HKSample]?){
DispatchQueue.main.async {
self.currentHeartRateSample = currentSampleTyple
//Get Last Sample of Heart Rate
self.currentHeartLastSample = self.currentHeartRateSample?.last
print("lastSample : \(String(describing: self.currentHeartLastSample))")
if self.currentHeartLastSample != nil {
let result = self.currentHeartLastSample as! HKQuantitySample
let heartRateBPM = result.quantity.doubleValue(for: HKUnit(from: "count/min"))
let heartRateBPMUnit = "count/min"
let deviceUUID = self.currentHeartLastSample?.uuid
let deviceIdentity = result.sourceRevision.source.name
let deviceProductName = self.currentHeartLastSample?.device?.name
let deviceProductType = result.sourceRevision.productType
let deviceOSVersion = result.sourceRevision.version
let startDate = self.currentHeartLastSample?.startDate
let endDate = self.currentHeartLastSample?.endDate
self.aCollectionView.reloadData()
}
}
}
I think the best method is to simply send the heart rate data to the phone app using Watch Communication.
In Watch code:
func send(heartRate: Int) {
guard WCSession.default.isReachable else {
print("Phone is not reachable")
return
}
WCSession.default.sendMessage(["Heart Rate" : heartRate], replyHandler: nil) { error in
print("Error sending message to phone: \(error.localizedDescription)")
}
}
and on phone you receive the data with:
func session(_ session: WCSession, didReceiveMessage message: [String: Any]) {
if let heartRate = message["Heart Rate"] {
print("Received heart rate: \(heartRate)")
} else {
print("Did not receive heart rate =[")
}
}
This should happen in pretty much real time. Alternatively there is another less reliable solution (imo) which is to just perform the heart rate query once every 5 seconds or so, but if I understand correctly you've already tried that and it didn't work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With