In my WatchOS app I've written the following code to check if my app has access to the user's health data:
func isHealthKitAuthorized() -> Bool {
let typesToRead: [HKObjectType] = [
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: .appleMoveTime)!,
HKObjectType.quantityType(forIdentifier: .appleExerciseTime)!,
HKObjectType.workoutType()
]
let typesToShare: Set<HKSampleType> = [
HKObjectType.workoutType(),
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: .heartRate)!
]
var isAuthorized = true
for type in typesToRead {
let status = healthStore.authorizationStatus(for: type)
if status != .sharingAuthorized {
print("Access denied to: \(type.identifier)")
isAuthorized = false
}
}
for type in typesToShare {
let status = healthStore.authorizationStatus(for: type)
if status != .sharingAuthorized {
print("Access denied to: \(type.identifier)")
isAuthorized = false
}
}
return isAuthorized
}
However for the appleMoveTime and appleExerciseTime types their status is returning as 'sharingDenied' (checked by printing the status' rawValue) even though they are authorized on the Watch's settings. This happened both on the simulator and on the Watch itself. Am I doing something wrong?
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
In the fitness app under iOS 18, the location of all workouts is displayed on a small map.
For workouts with routes, I can already successfully read out the route and thus also determine the starting point. So that works.
For indoor workouts such as yoga or indoor rowing, the exact location is also displayed in the fitness app. I would now also like to read out this location for these indoor workouts in my app.
Does anyone know how to do this?
Is it possible to develop the following app? The app will measure heart rate variability five times at 2-minute intervals triggered by an event and output the values.
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 associate heart rate (HR) data with a mindfulness session (HKCategoryTypeIdentifier.mindfulSession) in HealthKit, but I can’t find any documentation on how to do this.
I’ve seen third-party apps (like Medito) successfully log HR within Mindful Minutes, even when the session takes place on an iPhone (not an Apple Watch). However, when I try saving HR in the metadata, it does not appear in the Health app's Mindful Minutes section.
Code snippet:
func logMindfulnessSession(start: Bool, heartRate: Double? = nil) {
let mindfulType = HKCategoryType.categoryType(forIdentifier: .mindfulSession)!
let now = Date()
let endTime = now.addingTimeInterval(Double(selectedDuration))
var metadata: [String: Any]? = nil
if let hr = heartRate {
let heartRateUnit = HKUnit.count().unitDivided(by: HKUnit.minute())
let hrQuantity = HKQuantity(unit: heartRateUnit, doubleValue: hr)
metadata = ["heartRate": hrQuantity] // ❓ Is there a correct key for HR?
}
let sample = HKCategorySample(
type: mindfulType,
value: 0,
start: now,
end: endTime,
metadata: metadata
)
healthStore.save(sample) { success, error in
if let error = error {
print("HealthKit session save error: \(error.localizedDescription)")
} else {
print("Mindfulness session saved successfully.")
if let hr = heartRate {
print("Saved with HR: \(hr) BPM")
}
}
}
}
Questions:
What is the correct metadata key for associating heart rate with a mindful session?
Does HealthKit require a specific format (e.g., HKQuantitySample) for HR?
0 Are there additional permissions needed to allow HR to appear in Mindful Minutes?
Does HR need to be stored separately in HKQuantityTypeIdentifier.heartRate, and if so, how do third-party apps ensure it appears in the same entry as the mindful session?
thank you!
I implemented this to receive updates for specific data types and keep the latest daily information up to date. However, for some reason, it only works for a while before stopping completely.
Background Delivery
internal func backgroundDeliveryForReadTypes(enable: Bool, types: Set<HKQuantityType>) async {
do {
if enable {
try await statusForAuthorizationRequest(toWrite: [], toRead: types)
for type in types {
try await healthStore.enableBackgroundDelivery(for: type, frequency: .daily)
}
} else {
for type in types {
try await healthStore.disableBackgroundDelivery(for: type)
}
}
} catch {
debugPrint("Error enabling background delivery: \(error.localizedDescription)")
}
}
HKQueryAnchor
internal var walkingActivityQueryAnchor: HKQueryAnchor? {
get {
if let anchorData = UserDefaults.standard.data(forKey: "walkingActivityAnchor") {
return try? NSKeyedUnarchiver.unarchivedObject(ofClass: HKQueryAnchor.self, from: anchorData)
}
return nil
}
set {
if let newAnchor = newValue {
let anchorData = try? NSKeyedArchiver.archivedData(withRootObject: newAnchor, requiringSecureCoding: true)
UserDefaults.standard.set(anchorData, forKey: "walkingActivityAnchor")
} else {
UserDefaults.standard.removeObject(forKey: "walkingActivityAnchor")
}
}
}
HKAnchoredObjectQuery
internal func observeWalkingActivityInBackground(
_ start: Bool,
toRead: Set<HKQuantityType>,
completion: @escaping @Sendable (Result<WalkingActivityData?, Error>) -> Void
) {
if start {
guard (walkingActivityQuery == nil) else {
return
}
let predicate = getPredicate(date: Date())
let queryDescriptors = toRead.map {
HKQueryDescriptor(sampleType: $0, predicate: predicate)
}
let handleSamples: @Sendable (HKAnchoredObjectQuery, [HKSample]?, [HKDeletedObject]?, HKQueryAnchor?, Error?) -> Void = { [weak self] _, samples, _, newAnchor, error in
guard let self = self else { return }
if let error = error {
completion(.failure(error))
return
}
guard let samples = samples, !samples.isEmpty else {
completion(.success(nil))
return
}
Task {
self.walkingActivityQueryAnchor = newAnchor
let activity = await self.getWalkingActivity(date: Date())
completion(.success(activity))
}
}
let query = HKAnchoredObjectQuery(
queryDescriptors: queryDescriptors,
anchor: walkingActivityQueryAnchor,
limit: HKObjectQueryNoLimit,
resultsHandler: handleSamples
)
query.updateHandler = handleSamples
healthStore.execute(query)
walkingActivityQuery = query
} else {
if let query = walkingActivityQuery {
healthStore.stop(query)
walkingActivityQuery = nil
}
}
}
WalkingActivityData
private func getWalkingActivity(date: Date) async -> WalkingActivityData {
async let averageHeartRate = try await self.getAverageHeartRate(date: date)
async let steps = try self.getStepCount(date: date)
async let durationMinutes = try self.getTotalDurationInMinutes(date: date)
async let distanceMeters = try self.getDistanceWalkingRunning(date: date, unit: .meter())
async let activeCalories = try self.getActiveEnergyBurned(date: date)
return await WalkingActivityData(
date: date,
steps: try? steps,
activeCalories: try? activeCalories,
distanceMeters: try? distanceMeters,
durationMinutes: try? durationMinutes,
averageHeartRate: try? averageHeartRate
)
}
Example of getAverageHeartRate
func getAverageHeartRate(date: Date) async throws -> Double? {
let type = HKQuantityType(.heartRate)
_ = try checkAuthorizationStatus(for: type)
guard let heartRate = try await getDescriptor(
date: date,
type: type,
options: .discreteAverage
).result(for: healthStore)
.statistics(for: date)?
.averageQuantity()?.doubleValue(for: HKUnit.count().unitDivided(by: HKUnit.minute()))
else {
return nil
}
return Double(String(format: "%.2f", heartRate)) ?? 0.0
}
Descriptor & predicate
internal func getPredicate(startDate: Date, endDate: Date) -> NSCompoundPredicate {
let predicateForSamples = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
let excludeManual = NSPredicate(format: "metadata.%K != YES", HKMetadataKeyWasUserEntered)
return NSCompoundPredicate(andPredicateWithSubpredicates: [predicateForSamples, excludeManual])
}
internal func getDescriptor(startDate: Date, endDate: Date, type: HKQuantityType, options: HKStatisticsOptions) -> HKStatisticsCollectionQueryDescriptor {
let calendar = Calendar(identifier: .gregorian)
let anchorDate = calendar.date(bySetting: .hour, value: 0, of: startDate)!
var interval = DateComponents()
interval.day = 1
return HKStatisticsCollectionQueryDescriptor(
predicate: HKSamplePredicate.quantitySample(type: type, predicate: getPredicate(startDate: startDate, endDate: endDate)),
options: options,
anchorDate: anchorDate,
intervalComponents: interval
)
}
Implementation
public func observeWalkingActivityInBackground(_ start: Bool, toRead: Set<HKQuantityType>, memberID: String) {
observeWalkingActivityInBackground(start, toRead: toRead) { [weak self] result in
guard let self = self else { return }
}
}
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.
Hi,
I’m currently working on an app that utilizes sleep data from HealthKit to provide users with meaningful insights about their sleep.
To ensure a smooth user experience, I’d like to understand when sleep data collected by the Apple Watch is saved to the HealthKit store and when it gets synced to the iPhone.
Ideally, I want to fetch sleep data right after the user wakes up and opens our app. However, to do this reliably, I need to know the timing of how and when this data becomes available in the iPhone’s HealthKit store.
I’ve looked through the official documentation and relevant WWDC sessions but couldn’t find clear information on this topic.
If anyone has insights or experience with how and when the Apple Watch syncs HealthKit data—especially sleep records—to the iPhone, I’d greatly appreciate your input.
Thanks!
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);
}
};
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 was wondering which is the preferred way to send a lot of data from sensors of the apple watch to server.
It is preferred to send small chucks to iphone and then to server or directly send bulk data to server from watch. How does it affect battery and resources from watch ?
Are there any triggers that I can use to ensure best data stream. I need to send at least once a day. Can I do it in background or do I need the user to have my app in the foreground ?
Thank you in advance
Topic:
App & System Services
SubTopic:
Networking
Tags:
WatchKit
Health and Fitness
Network
Apple Watch
Has anyone seen the workout buddy options on watch OS yet? I am not able to get it on my watch.
My setup is an iPhone 16 and Watch Ultra 1 with the 26 OS
I am currently using beta 3.
English US language on both and US as region.
I am located in Germany though.
I restarted both devices multiple times without any changes.
Hopefully someone can help.
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Health and Fitness
watchOS
Apple Watch
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.
Hello, everyone!
I'm seeking some guidance on the App Store review process and technical best practices for a watchOS app.
My goal is to create an app that uses HealthKit to continuously monitor a user's heart rate in the background for sessions lasting between 30 minutes and 3 hours. This app would not be a fitness or workout tracker.
My primary question is about the best way to achieve this reliably while staying within the App Store Review Guidelines.
Is it advisable to use the WorkoutKit framework to start a custom, non-fitness "session" for the purpose of continuous background monitoring?
Are there any other recommended APIs or frameworks for this kind of background data collection on watchOS that I should be aware of?
What are the key review considerations I should be mindful of, particularly regarding Guideline 4.1 (Design) and the intended use of APIs?
My app's core functionality would require this kind of data for a beneficial purpose. I want to ensure my approach is technically sound and has the best chance of a successful review.
Any insights or advice from developers who have experience with similar use cases would be incredibly helpful!
Thank you!
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
SensorKit
Health and Fitness
watchOS
Watch Complications
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
I have FB12696743 open since July 21, 2023 and this happened again today.
I get home at approx 10 mins after the hour, walk appox 50 ft across my yard, up 5 steps into my house, let the dog out and pace on my deck watching the dog, go back in the house walk around the kitchen while preparing dinner. A total of about 200 ft. I sit down about 35 past the hour and start to eat and at 10 mins to the next our and I get the reminder to stand.
On the other side I wake up at 5 mins to hour. Walk 8 steps to the bathroom and successfully achieve the stand for that hour.
WHY!?!?!? 😁🤣
We currently use the HKCategoryValueMenstrualFlow enum to determine the type of menstrual flow: light, medium, etc. a user is having. We also use this enum in determining if it's an actual period day.
The Problem
I see HKCategoryValueMenstrualFlow was recently deprecated but has not been replaced by another data type.
Are there plans to replace/update it with another data type?
When or at what point in the future will this deprecation cause a problem in my code?
Hello,
I am building a workout app that has an option to add segments to differentiate different stages of the training session. Segments are added the following way:
func saveSegment(eventType: HKWorkoutEventType, startDate: Date, endDate: Date, inSeg: Int) async throws {
let dateInterval = DateInterval(start: startDate, end: endDate)
let event = HKWorkoutEvent(type: eventType, dateInterval: dateInterval, metadata: metadata)
try await builder?.addWorkoutEvents([event])
}
Inside Health -> Workouts -> Show All Data, the segments appear, but in Fitness app there are no segments. The workout is .paddleSports. I thought that maybe the workout type was the problem, but when I start the sessions from the native workout app, segments are added and shown in the Fitness app:
In other posts I saw suggested to add an event as .marker instead of .segment, but the result is the same, it does not appear.
Is there something I am doing wrong? How can I show the segments into the Fitness app?
Another question, I would like to add stroke rate and stroke count to my paddling session, is there a way to add it? Paddle Sports workout was recently introduced and it would be great to have the option to add those values.
Thank you in advance.
Inaki