Goal
I am currently trying to get the data to plot an elevation chart for a HKWorkout. I want the X-axis to represent distance and the Y-axis to represent elevation. This sort of graph is fairly common and acts as a sort of cross section of a workout route.
This is a rough mockup of the sort of chart I am hoping to plot.
Progress
I have successfully queried the WorkoutRoute for a given HKWorkout and I am able to get all of the recorded CLLocations in the route.
func getWorkoutRoute(for workout: HKWorkout) async -> [CLLocation]? {
let byWorkout = HKQuery.predicateForObjects(from: workout)
let samples = try? await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[HKSample], Error>) in
store.execute(HKAnchoredObjectQuery(type: HKSeriesType.workoutRoute(), predicate: byWorkout, anchor: nil, limit: HKObjectQueryNoLimit, resultsHandler: { (query, samples, deletedObjects, anchor, error) in
if let hasError = error {
continuation.resume(throwing: hasError); return
}
guard let samples = samples else { return }
continuation.resume(returning: samples)
}))
}
guard let route = (samples as? [HKWorkoutRoute])?.first else { return nil }
let locations = try? await withCheckedThrowingContinuation { (continuation: CheckedContinuation<[CLLocation], Error>) in
var allLocations = [CLLocation]() // built up over time as and when HK tells us
store.execute(HKWorkoutRouteQuery(route: route) { (query, locationsOrNil, done, errorOrNil) in
// This block may be called multiple times.
if let error = errorOrNil {
continuation.resume(throwing: error); return
}
guard let locations = locationsOrNil else {
fatalError("Invalid State: This can only fail if there was an error.")
}
allLocations += locations
if done {
continuation.resume(returning: allLocations)
}
})
}
return locations
}
Problem
Within each CLLocation I am able to access the elevation (so that's the y-axis sorted) but I am struggling to find out how to get the distance traveled for the given location.
CLLocation does has a method to get the distance between two locations but this is calculated as the crow flies
so will not give accurate values. The locations also include a timestamp.
The HKWorkout objects should include all the data I need to acutely get the distance I'm just not sure how.
Other health apps such as HealthFit are able to show get the data I am looking for so I know it must be possible.
Can anyone point me in the right direction?