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 }
}
}
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
We are seeing an issue where sending data using the asynchronous method HKWorkoutSession.sendToRemoteWorkoutSession(data: Data) will never return in some cases (no success nor failure).
This issue is happening for roughly 5% of Workouts started and will stay broken for the whole workout. The other 95% of the workouts, the connection works flawlessly. This happens on both watchOS 10 and 11, and with phones running iOS 17 or 18. The issue is quite random and not reproducible.
Our app has thousands of workouts a day that use the workout session workout data send, with constant messages being send every few seconds.
In some of those 5% cases the "sendToRemoteWorkoutSession" will throw way later, like 30+ minutes later, if the watch app is awake long enough to capture a log of a failure.
Our code uses the same flow as in the sample project:
https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/building_a_multidevice_workout_app
Here is some sample code, which is pretty simple.
Setup code:
let workoutSession = try HKWorkoutSession(healthStore: healthStore, configuration: configuration)
workoutSession.delegate = self
activeWorkoutSession?.startMirroringToCompanionDevice { success, error in
print("Mirroring started on companion device: \(success), error: \(error)")
}
workoutSession?.prepare()
then later we send data using the workout session:
do {
print("Will send data")
try await workoutSession.sendToRemoteWorkoutSession(data: data)
print("Successfully sent data") // This nor the error may be called after waiting extensive amounts of time
} catch {
print("Failed to send data, error: \(error)") // This nor the success may be called after waiting extensive amounts of time
}
So far, the only fix is to restart the phone and watch at the same time, which is not a great user experience.
Is anyone else seeing this issue? or know how to fix this issue?
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Watch Connectivity
Health and Fitness
watchOS
WorkoutKit
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.
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.
I am developing a React Native app for a health monitoring device that connects via Bluetooth and streams live data on iOS. To ensure the uniqueness of the device, I initially planned to use the MAC address. However, I discovered that iOS does not provide access to the original MAC address due to privacy restrictions.
Is there an alternative approach to uniquely identifying a Bluetooth device in iOS? I need a reliable way to distinguish devices while maintaining secure and stable connections.
Any insights or best practices on handling this in iOS would be greatly appreciated.
Looking forward to hearing your suggestions! If anyone has experience with handling Bluetooth device uniqueness on iOS, please share your insights. Thank you!
Topic:
App & System Services
SubTopic:
Core OS
Tags:
macOS
Health and Fitness
Core Bluetooth
Privacy
The WatchOS developer is not allowed to obtain healthKit permission status. The result is always unauthorized (either by clicking the dot/cross in the upper left corner or by turning on all Health, on some, off all).
WatchOS 开发获取 healthKit 的权限状态authorizationStatus不准。结果始终都是未授权(无论是点击左上角的点叉号还是开启全部健康项开关,开启部分,关闭所有),怎么处理?
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!
Hello,
I’m developing an iOS app that works with sleep data from Apple Watch via HealthKit. I would like to clarify the following:
How can an iPhone app detect when a sleep session ends on the Apple Watch?
When is sleep data typically written to the HealthKit store on iPhone after sleep ends? Is it immediately after wake-up, or does it depend on certain conditions (e.g., watch charging, connectivity)?
Understanding the timing and mechanism of sleep data synchronization is crucial for our app to process accurate and timely health information.
Thank you for your assistance.
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
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?
Based on Cooordinate with the companion app in this article by Apple
https://developer.apple.com/documentation/healthkit/running-workout-sessions
if a workout were to be started on the iPhone companion app but with no Watch available, given HKLiveWorkoutBuilder not available in iOS, does the iPhone app need to implement it's own workout tracking such as a timer for counting the elapsed time and location updates for distance and GPS tracking?
If so in an instance where a paired Apple Watch were to exist and the workout is continued in the Watch app should the iPhone companion app stop this custom workout tracking and revert to the mirrored workout from the Watch to ensure accurate and synchronised data between the apps?
读取是不是解析 metadata 的对应键来获取值对吧~但我看了相关开发文档好像没找到这个的键是什么~于是也没法写入到对应的,现在只能自定义键来进行写入
但是这样写入后无法显示在心情下方的影响因素后面~
这个 key 是没公开的吗还是说我方法弄错了~请各位大大指教
We are working on the health related application and use apple health kit to sync the data from different devices like watches or ring.
We are targeting oura ring to get sleep and other parameters data. We are able to sync the data from oura for all other parameters (like pulse, respiratory rate, blood pressure, etc..) other than sleep. Surprisingly, sleep data that comes through other devices is syncing as expected from the health kit. We are even getting the data which is added manually in health kit. The only sleep data not syncing is from oura.
Can we get a document or any kind of help to sync the data from oura in to our application using health kit?
For a given date, there are discrepancies between the step counts obtained from HealthKit and those displayed in the Health app. Is it possible for such discrepancies to occur even if step counts are not manually entered and multiple devices are not being used?
I want to know , how many days will the data of health stays in apple watch . For example, I have not synced the watch with iPhone for two weeks . Then When I synced it , I am only able to see the last week data on iPhone of the watch . Is it true ?
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!?!?!? 😁🤣
Hi everyone,
I'm building a health-focused iOS and watchOS app that uses WatchConnectivity to sync real-time heart rate and core body temperature data from iPhone to Apple Watch. While the HealthKit integration works correctly on the iPhone side, I'm facing persistent issues with WatchConnectivity — the data either doesn't arrive on the Watch, or session(_:didReceiveMessage:) never gets triggered.
Here's the setup:
On iPhone: Using WCSession.default.sendMessage(_:replyHandler:errorHandler:) to send real-time values every few seconds.
On Apple Watch: Implemented WCSessionDelegate, and session(_:didReceiveMessage:) is supposed to update the UI.
Both apps have WCSession.isSupported() checks, activate the session, and assign delegates correctly.
The session state shows isPaired = true and isWatchAppInstalled = true.
Bluetooth and Wi-Fi are on, both devices are unlocked and nearby.
Despite all this, the Watch never receives messages in real-time. Sometimes, data comes through in bulk much later or not at all.
I've double-checked Info.plist configurations and made sure background modes include "Uses Bluetooth LE accessories" and "Background fetch" where appropriate.
I would really appreciate guidance on:
Best practices for reliable, low-latency message delivery with WatchConnectivity.
Debugging steps or sample code to validate message transmission and reception.
Any pitfalls related to UI updates from the delegate method.
Happy to share further details. Thanks in advance!
Topic:
App & System Services
SubTopic:
Networking
Tags:
Watch Connectivity
Health and Fitness
watchOS
Apple Watch
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
I am very happy to see that HealthKit with OS26 is bringing HKLiveWorkoutDataSource to iOS and iPadOS. I have been replicating a similar type for the last several years for users that only have an iPhone.
I did notice that the data types that the different platform data sources collect automatically is different. That makes sense if you think exclusively about what the device can actually capture. Bluetooth HRM is the only Bluetooth SIG profile that is out-of-the-box supported for Apple Health on iOS and iPadOS (right?). Whereas watchOS 10 got all of the cycling sensors (woohoo!).
It would be great if the types to collect were the same across platforms even if the device couldn't collect the data now, because then in the future when / if new sensor support is added, it will be transparent to developers. Fantastic. Easier life as an indie / third party developer. At least that is the idea.
And yes, I know I can also write Core Bluetooth code and roll my own SIG implementation for the cycling profiles, but Apple already has this code in one os, 'just copy it, it will be easy'. I know that isn't the reality especially against the new ASK framework, but one can hope and dream right? Imagine how many more apps would contribute that data if it was supported out of the box. An alternative, GitHub is a great place for Apple to share their Core Bluetooth implementation of the SIG profiles :). Just another thought.
Here are some feedbacks related to this:
FB17931751 - HealthKit: Add built-in support for cycling sensors on iOS and iPadOS - copy paste the code from watchOS. It will be easy they said (June 2025)
FB12323089 - CoreBluetooth / Health / Bluetooth Settings: Add support for cycling sensors announced in watchOS 10 to iOS and iPadOS 17 (June 2023)
FB14311218 - HealthKit: Expected outdoor cycling to include .cyclingSpeed quantity type as a default HKLiveWorkoutDataSource type to collect (July 2024)
FB14978701 - Bluetooth / HealthKit / Fitness: Expose information about the user specified for Apple Watch paired Cycing Speed Sensor like isConnected and wheelCircumference values (August 2024)
FB18402258 - HealthKit: HKLiveWorkoutDataSource should collect same types on iOS and watchOS even if device cannot produce data today (June 2025)
FB14236080 - Developer Documentation / HealthKit: Update documentation for HKLiveWorkoutDataSource typesToCollect for which sample types are automatically collected by watchOS 10 and 11 (July 2024)
Tangentially related:
FB10281304 - HealthKit: Add HKActivityTypes canoeBikeRun and kayakBikeRun (June 2022)
FB10281349 - HealthKit: Add HKActivityType walkCanoeWalk and walkKayakWalk (June 2022)
FB7807993 - Add HKQuantityTypeIdentifier.paddleDistance for canoeing, kayaking, etc type workouts (June 2020)
FB12508654 - HealthKit / Settings / Bluetooth / Workouts: Cycling sensor support doesn't allow for 'bike selection' in use case of multiple bikes and multiple sensors (borrow a bike to ride together) - production usability issue (July 2023)
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Health and Fitness
HealthKit
Core Bluetooth
AccessorySetupKit
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?