Reputation: 81
I am sharing a workout to the HKStore and I have requested the following types tot read:
let typesToRead: Set = [
HKQuantityType.quantityType(forIdentifier: .heartRate)!,
HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning)!
]
In my workout session class (that tracks and records an active workout) I am able to record live data and save it to HealthStore but I don't know how to read that data and display it on screen for the users to view live during there workout. (or at least print the heart rate, activeEnergyBurned etc data in console).
Here is the HKLiveWorkoutBuilderDelegate that seems to be sharing the relevant workout data
// MARK: HKLiveWorkoutBuilderDelegate
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
for type in collectedTypes {
guard let quantityType = type as? HKQuantityType else {
return // Nothing to do
}
let statistics = workoutBuilder.statistics(for: quantityType)
let typeDescription = type.description
}
}
And here is how my workout is activated:
override func awake(withContext context: Any?) {
super.awake(withContext: context)
configuration.activityType = .running
configuration.locationType = .indoor
do {
session = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
builder = session.associatedWorkoutBuilder()
} catch {
dismiss()
return
}
// Setup session and builder
session.delegate = self
builder.delegate = self
builder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
// Start session and builder
session.startActivity(with: Date())
builder.beginCollection(withStart: Date()) { (success, error) in
self.setDurationTimerDate()
}
}
Note: I am using Apples new Beta WatchOS 5.0
Upvotes: 4
Views: 1188
Reputation: 808
You are doing most of the things, but you need to also enable the collecting of data to the dataSource
. In my app I collect distance and heart rate data, I do it like this:
let dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
if let hr = HKQuantityType.quantityType(forIdentifier: .heartRate) {
dataSource.enableCollection(for: hr, predicate: nil)
}
if let distance = HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning) {
dataSource.enableCollection(for: distance, predicate: nil)
}
workoutBuilder?.dataSource = dataSource
Then I can print that information in the HKLiveWorkoutBuilderDelegate
method like this:
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
guard let hrType = HKQuantityType.quantityType(forIdentifier: .heartRate),
let distanceType = HKQuantityType.quantityType(forIdentifier: .distanceWalkingRunning) else {
return
}
if collectedTypes.contains(hrType) {
if let hrQuantity = workoutBuilder.statistics(for: hrType)?.mostRecentQuantity() {
// We want to have BPM
let hrUnit = HKUnit(from: "count/min")
let hr = Int(hrQuantity.doubleValue(for: hrUnit))
debugPrint("HR: \(hr)")
}
}
if collectedTypes.contains(distanceType) {
if let distQuantity = workoutBuilder.statistics(for: distanceType)?.sumQuantity() {
// We want to have total distance in meters
let distance = distQuantity.doubleValue(for: HKUnit.meter())
debugPrint("Distance: \(distance) m")
}
}
}
And then I get in console:
"Distance: 6.5 m"
"Distance: 10.4 m"
"HR: 112"
"Distance: 14.3 m"
"HR: 117"
"Distance: 20.8 m"
Upvotes: 8