I'm reading hourly statistics from HealthKit using executeStatisticsCollectionQuery (code below).
Expectation
What I expect is to get back the list with one row per hour, where each hours has the same cumulative sum value.
Actual result
In results, first hour always contains less calories than next hours, which all have the same value.
Example:
Start: 2025-06-02T00:00:00+03:00, anchor: 2025-06-02T00:00:00+03:00, end: 2025-06-02T12:00:00+03:00
🟡 2025-06-02T00:00:00+03:00 Optional(50.3986 kcal)
🟡 2025-06-02T01:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T02:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T03:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T04:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T05:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T06:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T07:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T08:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T09:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T10:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T11:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T12:00:00+03:00 Optional(14.0224 kcal)
As you can see, here we have 2025-06-02T00:00:00+03:00 Optional(50.3986 kcal)
Now, if I add one more hour to the request (from beginning of time window), the same hour has proper calories count, while newly added hour, has wrong value):
2025-06-01T23:00:00+03:00, anchor: 2025-06-01T23:00:00+03:00, end: 2025-06-02T12:00:00+03:00.
🟡 2025-06-01T23:00:00+03:00 Optional(50.3986 kcal)
🟡 2025-06-02T00:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T01:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T02:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T03:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T04:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T05:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T06:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T07:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T08:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T09:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T10:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T11:00:00+03:00 Optional(64.421 kcal)
🟡 2025-06-02T12:00:00+03:00 Optional(14.0224 kcal)
And now first hour of the day, magically has more calories burned: 2025-06-02T00:00:00+03:00 Optional(64.421 kcal)
I suspect similar things happen with other quantity types, but haven't yet found a way to reproduce it.
Am I doing something wrong or is it a bug in HealthKit?
Code
let anchorDate = startDate
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate, options: [.strictStartDate])
healthStore.executeStatisticsCollectionQuery(
quantityType: .basalEnergyBurned,
quantitySamplePredicate: predicate,
options: [.separateBySource, .cumulativeSum],
anchorDate: anchorDate,
intervalComponents: DateComponents(hour: 1),
initialResultsHandler: { statistics, error in
if let error = error {
log(.error, "Error retrieving steps: \(error.localizedDescription)")
continuation.resume(throwing: SpikeException("Error retrieving steps: \(error.localizedDescription)"))
return
}
if let statistics {
let f = ISO8601DateFormatter()
f.timeZone = TimeZone.current
for s in statistics {
log(.debug, "\(f.string(from: s.startDate)) \(s.sumQuantity())")
}
}
continuation.resume(returning: statistics ?? [])
}
)
Use HealthKit to enable your iOS and watchOS apps to work with the Apple Health app.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
Hello everyone, my app is designed to help people sleep. It has been rejected multiple times due to issues with version 1.4.1 during the submission process. However, the app simply evaluates users’ insomnia and anxiety status based on their responses to questions and provides some relaxation methods. It does not involve any medical-related content. The reviewer provided screenshots of the assessment results page and some relaxation techniques. How should I handle this issue?
Hi everyone,
while testing HKWorkoutSession with HKLiveWorkoutBuilder on iOS 26 Beta (cycling workout), I noticed the following behavior:
– Starting a cycling HKWorkoutSession automatically connects to my Bluetooth heart rate monitor and records HR into HealthKit ✅
– However, my Bluetooth cycling power meter and cadence sensor (standard BLE Cycling Power & CSC services) are not connected automatically, and no data is recorded into HealthKit ❌
On Apple Watch, when starting a cycling workout, these sensors do connect automatically and their data is written to HealthKit — which is exactly what I would expect on iOS as well.
Question:
Is this by design, or is support for power and cadence sensors planned for iOS in the same way as on watchOS?
Or do we, as developers, need to implement the BLE Cycling Power and CSC profiles ourselves (via CoreBluetooth) if we want these metrics?
Environment:
– iOS 26 Beta
– HKWorkoutSession & HKLiveWorkoutBuilder (cycling)
– Bluetooth HRM connects automatically
– BLE power & cadence sensors do not
This feature would make it much easier to develop cycling apps with full HealthKit integration, and also create a more consistent user experience compared to watchOS.
Thanks for any insights!
Topic:
App & System Services
SubTopic:
Hardware
Tags:
Health and Fitness
HealthKit
Core Bluetooth
WorkoutKit
New in iOS 26 and WatchOS 26 is a Sleep Score calculation for users based on Duration, Bedtime and Interruptions.
Unfortunately I can't find any APIs for developers to tap into this metric. Yes, in theory it's all created off the same Sleep Analysis data already available with HealthKit but that makes it very hard to recreate in our apps. If the numbers don't match up exactly, users will understandably complain.
Can anyone confirm that this is the case and I've not missed a Sleep Score API? I'll then file feedback.
Hopefully this doesn't go the way of Heart Rate Zones where the Apple Watch iPhone app has generated them for years and provided no way for third party apps to access these values (yes many feedbacks provided previously).
Is there way to read the Apple Heart rate zones from HealthKit? I want to read the min/max bpm for each of the 1-5 zones.
I went through the Apple HealthKit developer documentation but couldn't find it https://developer.apple.com/documentation/healthkit
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
iOS
watchOS
Health and Fitness
HealthKit
I need to be able to create and store a HeartbeatSeries for a given time-period from an Apple Watch, to then retrieve that data from HealthKit to be processed.
I have working code which allows me to begin a workout session, which is being used to determine how long a session has been running for. I also have working code for retrieving HeartbeatSeries data from HealthKit.
The issue is that no HeartbeatSeries data is being stored into HealthKit as a result of the workout session running. Whether that session is running for as little as 30 seconds or as long as 20 minutes, nothing is stored.
However, when I use the the Apple "Meditation" app (formerly known as "Breathe"), I can query HealthKit afterwards and retrieve a list of individual heartbeat timings during that 2 minute period.
Therefore, it IS possible to store a HeartbeatSeries from within an app on the Apple Watch.
What I would like to know is, how can I use the pulse sensor built-in to the Apple Watch to be able to record a HeartbeatSeries similar to how the Meditation app does it.
My research group is using watch sensors (accelerometers, gyroscopes) to track wrist motion to detect and measure eating. https://cecas.clemson.edu/ahoover/bite-counter/
We are running an HKWorkoutSession on the watch so that the app can run for an extended period of time (up to 12 hr) and continue to sense and process motion data.
Our app is adding to the activity rings, making it look like the user is exercising the entire time our app is running. Is there a method to prevent our app from contributing to the activity ring measures?
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
WatchKit
Health and Fitness
SensorKit
WorkoutKit
Are there any HealthKit related changes to be aware of in the new update that enables SPO2 / Blood Oxygen Saturation measurements on certain Apple Watch models within the US?
I’m aware of processing happening on the phone…. But beyond that:
Does this mean values are then saved to Apple Health?
Do these models still take background SPO2 measurements in the same way as other models do?
Are these values then visible in third party iOS apps as normal through HealthKit?
Do these values sync back to the paired Apple Watch HealthKit store for third party apps to access on the Watch?
For reference I have an iOS and WatchOS app that, amongst other features, provides the ability to see your SPO2 values in the Watch app, complications and in the iOS app.
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
WatchKit
Health and Fitness
watchOS
HealthKit
According to the WWDC25 Presentation Track workouts with HealthKit on iOS and iPadOS, there is supposed to be a new property for restoring an active workout after a crash on iOS/iPadOS. The developer documentation also supports this. However, this property does not seem to exist in the latest Xcode 26 beta, even in projects targeting iOS 26.0 as the minimum version.
Am I missing something? Has this property not been made available yet? It is actually looking like all of the new iOS 26.0 properties are missing UIScene.ConnectionOptions on my system.
Is there anywhere that describes in detail how third party workout apps can use the new effort score functionality? I can't see much in the documentation or any of the WWDC videos.
In particular it would be useful to know if an effort score is automatically calculated for workouts created with third party apps? It doesn't seem to happen but some people say it takes weeks / months before watchOS starts calculating it for third party apps.
If it doesn't happen automatically then how can the app set it? I tried the new relateWorkoutEffortSample API but that didn't work for me (see https://developer.apple.com/forums/thread/763539).
If I could get it working then how should I determine a default effort score based on the workout metrics? Is that something that the app should do? If so then it would be good to be consistent with watchOS so some idea of how that is calculating effort scores would be useful.
Sorry for all the questions, especially if there is an article in the documentation or a video that I have missed.
Platform & Version:
iOS Version: 18.3.1
Development Environment: Xcode 16.2, macOS 14.6.1
Description of the Issue:
We're exploring ways to better integrate Apple Fitness+ workouts into our app. We've noticed that some third-party apps, such as Strava and HealthFit, now display Fitness+ workout details, including the title, trainer, and an image.
I’ve been investigating how this is possible, and the only relevant change I’ve found is that HKMetadataKeyAppleFitnessPlusCatalogIdentifier is now being set for Fitness+ workouts. However, I can’t find any public API or official documentation that explains how to use these identifiers to retrieve the associated workout details.
Question:
Is there an official API available to fetch metadata for Fitness+ workouts using these identifiers? Or are these third-party apps potentially accessing private APIs? If no API exists, is the only option to create a manual mapping of these identifiers—something that seems impractical given the constantly evolving Fitness+ workout catalog?
Any guidance on this would be greatly appreciated. Thanks!
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Health and Fitness
HealthKit
WorkoutKit
The background deliver works perfectly when the app is in the background or suspended states. However, when the app is killed (terminated state), the background task does not execute
I'm trying to hook into the new workoutEffort score supported in iOS 18, I am collecting this information from users when they submit their workout and trying to add a sample to the HKWorkout in the same manner as I've been adding other samples like bodyweight, calories burned, etc.
I'm receiving the error:
HKWorkout: Sample of type HKQuantityTypeIdentifierWorkoutEffortScore must be related to a workout
I tried adding the samples using HKWorkoutBuilder.add([samples]) as which has been working perfectly for calories burned & bodyweight, but I am receiving the above error for workoutEffortScore
As a second approach, I tried adding the sample after I called finishWorkout on the HKWorkoutBuilder and received back the HKWorkout object using HKHealthStore.add([samples], to: HKWorkout) and am still receiving the same error!
I don't know otherwise how to relate a sample to a workout, I thought those were the APIs to do so? I'm using Xcode 16.0 RC (16A242) and testing on an iOS 16 Pro simulator
Hi everyone!
I'm trying to get the total sleep time for a given day, but users report that there's a difference between what my app reports and what the Apple Health app reports. In particular, we're off by 2 minutes less on average.
What we're doing is:
Get all the samples that are either core, deep, rem or unspecified
Cut-off time at 3 PM previous day
Merge overlapping intervals
Add all the remaining intervals
For debugging purposes I'm storing and sending all the raw samples to a server, and I have run tests and I don't find anything wrong. It looks like the number we come up with is correct according to our own rules. I wonder, how is Apple adding up all the samples to arrive at a number that's slightly off to our number.
Any insight would be appreciated. Thanks.
When I set the distanceFilter = 5 (5 meters) in the GPS CLLocationManager
I can't display the workout routes in the Apple Fitness app after writing the recorded GPS data to HealthKit via HKWorkoutRouteBuilder.
The smaller distanceFilter, Fitness will displays the route.
Should I consider setting up a small distanceFilter when developing a workout app on watchOS?
I'm using Healthkit with the following H/W specs:
Apple Watch, series 8, OS: 10.6.1 (21U580)
iPhone 11 Pro, OS: 17.6.1
Mac Studio M1
Xcode ver: 16.0 (16A242d)
I am trying to get Apple Watch to report heart rate, HRV, respiratory rate, and body temperature using Healthkit's HKLiveWorkoutBuilder implementing HKLiveWorkoutBuilderDelegate's workoutBuilder method. However, the only reported value that is found from the workoutBuilder method's collectedTypes (a Set of HKSampleType objects) is HKQuantityTypeIdentifierHeartRate. Nothing for HRV, respiratory rate, or body temperature. All entitlements are set up, the plist filled in, and capabilities in place. Not sure why only the heart rate is reported from the watch but nothing else.
I've scoured StackOverflow, Apple developer forums, even ChatGPT but none of the solutions work.
Any help most appreciate!
The model code is:
import Foundation
import HealthKit
class WatchModel: NSObject, HKLiveWorkoutBuilderDelegate, HKWorkoutSessionDelegate {
private let healthStore = HKHealthStore()
private var workoutSession: HKWorkoutSession!
private var workoutBuilder: HKLiveWorkoutBuilder!
override init() {
super.init()
requestAuthorization()
startWorkoutSession()
}
private func requestAuthorization() {
let heartRateType = HKQuantityType.quantityType(forIdentifier: .heartRate)!
let respiratoryRateType = HKQuantityType.quantityType(forIdentifier: .respiratoryRate)!
let HRVRateType = HKQuantityType.quantityType(forIdentifier: .heartRateVariabilitySDNN)!
let temperatureRateType = HKQuantityType.quantityType(forIdentifier: .bodyTemperature)!
let healthDataTypes: Set = [heartRateType, respiratoryRateType, HRVRateType, temperatureRateType]
healthStore.requestAuthorization(toShare: healthDataTypes, read: healthDataTypes) { (success, error) in
if !success {
print("Authorization failed")
}
}
}
func workoutSession(_ workoutSession: HKWorkoutSession, didChangeTo toState: HKWorkoutSessionState, from fromState: HKWorkoutSessionState, date: Date) {
}
func workoutSession(_ workoutSession: HKWorkoutSession, didFailWithError error: any Error) {
}
func workoutBuilderDidCollectEvent(_ workoutBuilder: HKLiveWorkoutBuilder) {
}
func startWorkoutSession() {
let configuration = HKWorkoutConfiguration()
configuration.activityType = .other
configuration.locationType = .indoor
do {
workoutSession = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
workoutBuilder = workoutSession.associatedWorkoutBuilder()
workoutBuilder.delegate = self
workoutBuilder.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
let dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: configuration)
let respiratoryRate = HKQuantityType(.respiratoryRate)
dataSource.enableCollection(for: respiratoryRate, predicate: nil)
let bodyTemp = HKQuantityType(.bodyTemperature)
dataSource.enableCollection(for: bodyTemp, predicate: nil)
let hrv = HKQuantityType(.heartRateVariabilitySDNN)
dataSource.enableCollection(for: hrv, predicate: nil)
workoutSession.delegate = self
workoutSession.startActivity(with: Date())
workoutBuilder.beginCollection(withStart: Date(), completion: { (success, error) in
if let error = error {
print("Error starting collection: \(error.localizedDescription)")
}
})
} catch {
print("Failed to start workout session: \(error.localizedDescription)")
}
}
func workoutBuilder(_ workoutBuilder: HKLiveWorkoutBuilder, didCollectDataOf collectedTypes: Set<HKSampleType>) {
print("collected types: \(collectedTypes)")
for type in collectedTypes {
if let quantityType = type as? HKQuantityType {
if quantityType == HKQuantityType.quantityType(forIdentifier: .heartRate) {
if let heartRateQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let heartRateUnit = HKUnit(from: "count/min")
let heartRateValue = heartRateQuantity.doubleValue(for: heartRateUnit)
print("heart rate: \(heartRateValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .heartRateVariabilitySDNN) {
if let hrvQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let hrvUnit = HKUnit.secondUnit(with: .milli)
let hrvValue = hrvQuantity.doubleValue(for: hrvUnit)
print("HRV: \(hrvValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .bodyTemperature) {
if let bodyTempQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let tempUnit = HKUnit.degreeCelsius()
let tempValue = bodyTempQuantity.doubleValue(for: tempUnit)
print("body temp: \(tempValue)")
}
}
if quantityType == HKQuantityType.quantityType(forIdentifier: .respiratoryRate) {
if let respRateQuantity = workoutBuilder.statistics(for: quantityType)?.mostRecentQuantity() {
let respRateUnit = HKUnit(from: "count/min")
let respRateValue = respRateQuantity.doubleValue(for: respRateUnit)
print("breathing: \(respRateValue)")
}
}
}
}
}
}
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
watchOS
Health and Fitness
HealthKit
Apple Watch
Hi, i'm trying to get the number of step counts a person has taken. I decided to pull the data from health kit and the number of steps are incorrect. Come to find out apple health recommends an app called pedometer++ for the number of steps counted and after testing I realized that they are getting the correct number of steps a person is taking. How can I pull the correct number of steps a person has taken? I want to be able to merge the data from watch and phone to make sure we are getting the correct number of steps but not double counting the steps either.
any guidance on this would be appreciated!
Here's the code snippet that i'm using right now:
permissions: {
read: [AppleHealthKit.Constants.Permissions.StepCount],
write: [],
},
};
AppleHealthKit.initHealthKit(permissions, error => {
if (error) {
console.log('Error initializing HealthKit: ', error);
return;
} else {
dispatch(setAllowHealthKit(true));
getHealthKitData();
console.log('HealthKit initialized successfully');
}
});
const getHealthKitData = async () => {
try {
const today = new Date();
const options = {
startDate: new Date(today.setHours(0, 0, 0, 0)).toISOString(),
endDate: new Date().toISOString(),
};
const steps = await new Promise((resolve, reject) => {
AppleHealthKit.getStepCount(options, (error, results) => {
if (error) reject(error);
resolve(results?.value);
});
});
setStepsCount(steps);
} catch (error) {
console.error('Error fetching HealthKit data:', error);
}
};