In iOS 26, HKLiveWorkoutBuilder is supported, which we can use like HKWorkoutSession in watchOS - this is very exciting.
However, it currently seems to have a bug in calculating calories.
I tested it in my app, and for nearly 6 minutes with an average heart rate of 134, it only calculated 8 calories consumed (80 calories per hour), including basal consumption, which is obviously incorrect.
(I used Powerboats Pro 2 connected to my phone, which includes heart rate data, and HKLiveWorkoutBuilder correctly collected the heart rate, which is great.)
I think my code is correct.
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)
if let statistics = statistics {
switch statistics.quantityType {
case HKQuantityType.quantityType(forIdentifier: .heartRate):
/// - Tag: SetLabel
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let value = statistics.mostRecentQuantity()?.doubleValue(for: heartRateUnit)
let roundedValue = Double( round( 1 * value! ) / 1 )
if let avg = statistics.averageQuantity()?.doubleValue(for: heartRateUnit) {
self.avgHeartRate = avg
}
self.delegate?.didUpdateHeartBeat(self, heartBeat: Int(roundedValue))
case HKQuantityType.quantityType(forIdentifier: .activeEnergyBurned):
let energyUnit = HKUnit.kilocalorie()
let value = statistics.sumQuantity()?.doubleValue(for: energyUnit)
self.totalActiveEnergyBurned = Double(value!)
print("didUpdate totalActiveEnergyBurned: \(self.totalActiveEnergyBurned)")
self.delegate?.didUpdateEnergyBurned(self, totalEnergy: self.totalActiveEnergyBurned + self.totalBasalEneryBurned)
return
case HKQuantityType.quantityType(forIdentifier: .basalEnergyBurned):
let energyUnit = HKUnit.kilocalorie()
let value = statistics.sumQuantity()?.doubleValue(for: energyUnit)
self.totalBasalEneryBurned = Double(value!)
print("didUpdate totalBasalEneryBurned: \(self.totalBasalEneryBurned)")
self.delegate?.didUpdateEnergyBurned(self, totalEnergy: self.totalActiveEnergyBurned + self.totalBasalEneryBurned)
return
default:
print("unhandled quantityType=\(statistics.quantityType) when processing statistics")
return
}
}
I think I've found the source of the problem:
let workoutConfiguration = HKWorkoutConfiguration()
workoutConfiguration.activityType = .traditionalStrengthTraining //walking, running is ok
workoutConfiguration.locationType = .outdoor
When I set the activityType to walking or running, the calorie results are correct, showing several hundred calories per hour.
However, when activityType is set to traditionalStrengthTraining or jumprope, the calculations are incorrect.
PS: I'm currently using Xcode 26 beta3 and iOS 26 beta3.
Hope this issue can be resolved. Thanks.