Most of the HealthKit sample code uses an InterfaceController
to serve as a HKWorkoutSessionDelegate
however I'm trying to set up a HealthStoreManager class that will serve as a HKWorkoutSessionDelegate and take this business logic away from any of my individual InterfaceControllers
responsibility, however the below code fails to start a workout, can anyone see my error?
InterfaceController: {
func segueToWorkoutInterfaceControllerWithContext() {
// Create workout configuration
let workoutConfiguration = HKWorkoutConfiguration()
workoutConfiguration.activityType = .running
workoutConfiguration.locationType = .outdoor
do {
let workoutSession = try HKWorkoutSession(configuration: workoutConfiguration)
let healthStoreManager = HealthStoreManager()
workoutSession.delegate = healthStoreManager
healthStoreManager.start(workoutSession)
} catch {
fatalError(error.localizedDescription)
}
let contextDictionary = ["workoutConfiguration" : workoutConfiguration, "ActivityType": selectedActivityType] as [String : Any]
// Pass configuration to next interface controller
WKInterfaceController.reloadRootPageControllers(withNames: ["WorkoutControlsInterfaceController", "MainDisplayInterfaceController", "SpeedInterfaceController", "CaloriesAndDistanceInterfaceController"],
contexts: [contextDictionary],
orientation: .horizontal,
pageIndex: 1)
}
}
}
class HealthStoreManager: NSObject, CLLocationManagerDelegate, HKWorkoutSessionDelegate {
private let healthStore = HKHealthStore()
// MARK: - HKWorkoutSessionDelegate
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: Error) {
print("workout session did fail with error: \(error)")
}
func workoutSession(_ workoutSession: HKWorkoutSession,
didChangeTo toState: HKWorkoutSessionState,
from fromState: HKWorkoutSessionState,
date: Date) {
DispatchQueue.main.async {
self.handleWorkoutSessionState(didChangeTo: toState, from: fromState)
}
}
func workoutSession(_ workoutSession: HKWorkoutSession, didGenerate event: HKWorkoutEvent) {
DispatchQueue.main.async {
//self.healthStoreManager.workoutEvents.append(event)
}
}
private func handleWorkoutSessionState(didChangeTo toState: HKWorkoutSessionState,
from fromState: HKWorkoutSessionState) {
switch (fromState, toState) {
case (.notStarted, .running):
print("workout started")
case (_, .ended):
default:
break
}
}
}
I found my error, I needed to pass the healthStoreManager instance into the context in order to avoid this class from being deallocated:
let contextDictionary = ["workoutConfiguration" : workoutConfiguration, "ActivityType": selectedActivityType, "healthStoreManager" : healthStoreManager] as [String : Any]