HealthKit HKWorkout totalEnergyBurn

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?

Apple Developer Forums would be a better place to ask, but in the HKWorkout docs it says:

To affect the rings, you must associate one or more active energy burned samples with the workout.

Are you doing that?

I was not doing that and adding that part fixed it! Thanks so much! Here is my new code. Note the comments about a minor issue.

        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)
            }
        }

From the docs (yellow box "Concurrency Note"), the async version is addSamples:

try await store.addSamples([sample], to: workout)

Thanks! I was trying to call the add method as an async method, but I needed to use addSamples instead.

1 Like