HealthKit HKWorkout totalEnergyBurned

I have an app that adds cycling workouts to HealthKit. Here is the snippet of code that does it.

        let workout = HKWorkout(
            activityType: HKWorkoutActivityType.cycling,
            start: startTime,
            end: endTime,
            duration: 0, // compute from start and end data
            totalEnergyBurned: HKQuantity(
                unit: .largeCalorie(),
                doubleValue: Double(calories)
            ),
            totalDistance: HKQuantity(unit: .mile(), doubleValue: distance),
            metadata: nil
        )
        try await store.save(workout)

This successfully adds a workout and the number of calories is recorded in the Health app. However, the iOS Fitness app and the watchOS Activity app do not recognize the calories so the MOVE ring is not affected. What else do I need to do to let those apps know that my workout burned calories?

It turns out I needed to add a sample to the workout as shown below. But see the comments in the code below about an issue with using the async version of the add method.

        let energyBurned = HKQuantity(
            unit: .largeCalorie(),
            doubleValue: Double(calories)
        )
        let workout = HKWorkout(
            activityType: HKWorkoutActivityType.cycling,
            start: startTime,
            end: endTime,
            duration: 0, // compute from start and end data
            totalEnergyBurned: energyBurned,
            totalDistance: HKQuantity(unit: .mile(), doubleValue: distance),
            metadata: nil
        )
        try await store.save(workout)

        let energyBurnedType = HKObjectType.quantityType(
            forIdentifier: HKQuantityTypeIdentifier.activeEnergyBurned
        )!
        let sample = HKQuantitySample(
            type: energyBurnedType,
            quantity: energyBurned,
            start: startTime,
            end: endTime
        )

        // Says "Missing argument for parameter 'completion' in call".
        // await store.add([sample], to: workout)

        // Says "Consider using asynchronous alternative version",
        // but I tried that above and it doesn't work!
        store.add([sample], to: workout) { _, error in
            if let error {
                print("error adding sample:", error)
            }
        }

A better approach would be to use the HKWorkoutBuilder class which will do the association and save for you. Take a look at HKWorkoutBuilder

HealthKit HKWorkout totalEnergyBurned
 
 
Q