Hello,
I am developing an Apple Watch app in Swift and SwiftUI that needs to receive real-time heartbeat data to visualize the time intervals between heartbeats. The app draws circles on the screen where the size and position of each circle are based on the time interval between consecutive heartbeats.
I am currently using the HKQuantityType for .heartRate from HealthKit to get heart rate data and calculate the intervals. However, I am wondering if this is the best approach for my requirement. I came across the HKElectrocardiogram class, and I am not sure if it would be a better fit for obtaining real-time heartbeat intervals.
My questions are:
Real-Time Heartbeats:
Is HKQuantityType for .heartRate the most appropriate way to get real-time heartbeat data for calculating intervals between beats?
Can HKElectrocardiogram provide real-time heartbeat intervals, or is it more suited for detailed ECG recordings rather than instantaneous heartbeats?
Accuracy and Performance:
Which method provides the most accurate and real-time data for heartbeat intervals?
Are there any other APIs or services in the Apple Watch ecosystem that I should consider for this purpose?
Best Practices:
What are the best practices for implementing real-time heartbeat monitoring in an Apple Watch app?
Are there any sample projects or documentation that could help me understand the optimal way to achieve this?
Here is a brief overview of my current implementation using HKQuantityType for .heartRate:
import Foundation
import HealthKit
class HeartRateMonitor: NSObject, ObservableObject {
@Published var heartRate: Double = 0.0
@Published var intervals: [TimeInterval] = []
private var lastHeartRateTimestamp: Date?
private var healthStore: HKHealthStore?
private let heartRateQuantityType = HKObjectType.quantityType(forIdentifier: .heartRate)
private let appStartTime: Date
override init() {
self.appStartTime = Date()
super.init()
if HKHealthStore.isHealthDataAvailable() {
self.healthStore = HKHealthStore()
self.requestAuthorization()
}
}
private func requestAuthorization() {
guard let heartRateQuantityType = self.heartRateQuantityType else { return }
healthStore?.requestAuthorization(toShare: nil, read: [heartRateQuantityType]) { success, error in
if success {
self.startMonitoring()
}
}
}
func startMonitoring() {
guard let heartRateQuantityType = self.heartRateQuantityType else { return }
let query = HKAnchoredObjectQuery(
type: heartRateQuantityType,
predicate: nil,
anchor: nil,
limit: HKObjectQueryNoLimit) { (query, samples, deletedObjects, newAnchor, error) in
guard let samples = samples as? [HKQuantitySample] else { return }
self.process(samples: samples)
}
query.updateHandler = { (query, samples, deletedObjects, newAnchor, error) in
guard let samples = samples as? [HKQuantitySample] else { return }
self.process(samples: samples)
}
healthStore?.execute(query)
}
private func process(samples: [HKQuantitySample]) {
for sample in samples {
if sample.endDate > appStartTime {
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let heartRate = sample.quantity.doubleValue(for: heartRateUnit)
DispatchQueue.main.async {
self.heartRate = heartRate
if let lastTimestamp = self.lastHeartRateTimestamp {
let interval = sample.endDate.timeIntervalSince(lastTimestamp)
self.intervals.append(interval)
}
self.lastHeartRateTimestamp = sample.endDate
}
}
}
}
}
Thank you for your guidance and suggestions!