I’m trying to use BGProcessingTaskRequest to fetch step data in the background and send it. However, when I combine BGProcessingTaskRequest, HKObserverQuery, and healthStore.enableBackgroundDelivery, the results sometimes return zero. When I don’t schedule the BGProcessingTaskRequest, the data retrieved using HKObserverQuery and HKSampleQueryDescriptor is correct.
// Register Smart Walking Sync Task
func registerSmartWalkingSync() {
#if !targetEnvironment(simulator)
BGTaskScheduler.shared.register(forTaskWithIdentifier: BGTaskIdentifier.smartwalking.rawValue, using: nil) { task in
guard let task = task as? BGProcessingTask else { return }
self.handleSmartWalkingSync(task: task)
}
#endif
}
func scheduleSmartWalkingSync(in seconds: TimeInterval? = nil, at date: Date? = nil) {
let newRequest = BGProcessingTaskRequest(identifier: BGTaskIdentifier.smartwalking.rawValue)
newRequest.requiresNetworkConnectivity = true
newRequest.requiresExternalPower = false
if let seconds = seconds {
newRequest.earliestBeginDate = Date().addingTimeInterval(seconds)
} else if let date = date {
newRequest.earliestBeginDate = date
}
do {
try BGTaskScheduler.shared.submit(newRequest)
debugPrint("✅ [BGTasksManager] scheduled for Smart Walking Sync")
} catch {
FirebaseConnection.shared.recordException(error)
debugPrint("❌ [BGTasksManager] error: \(error)")
}
}
// Handle Smart Walking Sync Task
func handleSmartWalkingSync(task: BGProcessingTask) {
debugPrint("🔄 [BGTasksManager] sync \(task.identifier) sync started")
scheduleSmartWalkingSync(in: SYNC_SMARTWALKING_TIME_INTERVAL)
let queue = OperationQueue()
let operation = HealthActivitiesOperation()
operation.completionBlock = {
Task {
do {
try await operation.sync()
task.setTaskCompleted(success: !operation.isCancelled)
debugPrint("✅ [BGTasksManager] sync \(task.identifier) completed successfully")
} catch {
FirebaseConnection.shared.recordException(error)
task.setTaskCompleted(success: false)
debugPrint("❌ [BGTasksManager] sync \(task.identifier) error: \(error)")
}
}
}
task.expirationHandler = {
operation.cancel()
}
queue.addOperation(operation)
}
// MARK: - HealthKit Background Delivery
internal func enableBackgroundDeliveryForAllTypes() async throws {
for type in allTypes.filter({ type in
type != HKQuantityType(.heartRate)
}) {
try await healthStore.enableBackgroundDelivery(for: type, frequency: .daily)
}
debugPrint("✅ [HealthKitManager] Enable Background Delivery")
}
internal func observeHealthKitQuery(predicate: NSPredicate?) async throws -> Set<HKSampleType> {
let queryDescriptors: [HKQueryDescriptor] = allTypes
.map { type in
HKQueryDescriptor(sampleType: type, predicate: predicate)
}
return try await withCheckedThrowingContinuation { continuation in
var hasResumed = false
let query = HKObserverQuery(queryDescriptors: queryDescriptors) { query, updatedSampleTypes, completionHandler, error in
if hasResumed {
return
}
if let error = error {
continuation.resume(throwing: error)
} else {
continuation.resume(returning: updatedSampleTypes ?? [])
}
hasResumed = true
completionHandler()
}
healthStore.execute(query)
}
}
internal func getHealthActivity(by date: Date, predicate: NSCompoundPredicate, sampleTypes: Set<HKSampleType>) async throws -> HealthActivityData {
var data = HealthActivityData(steps: 0, calories: 0, distance: 0.0, distanceCycling: 0.0, totalDuration: 0, date: date, heartRate: nil)
for sampleType in sampleTypes {
guard let quantityType = sampleType as? HKQuantityType else {
continue
}
switch quantityType {
case HKQuantityType(.stepCount):
let stepCount = try await getDescriptor(
date: date,
type: quantityType
).result(for: healthStore)
.statistics(for: date)?.sumQuantity()?.doubleValue(for: HKUnit.count())
data.steps = stepCount ?? 0.0
// Calculate total duration using HKSampleQueryDescriptor
let totalDurationDescriptor = HKSampleQueryDescriptor(
predicates: [.quantitySample(type: quantityType, predicate: predicate)],
sortDescriptors: [SortDescriptor(\.endDate, order: .reverse)]
)
let stepSamples = try await totalDurationDescriptor.result(for: healthStore)
data.totalDuration += stepSamples
.reduce(0) { $0 + $1.endDate.timeIntervalSince($1.startDate) } / 60.0
default:
debugPrint("Unknown quantity type")
}
}
return data
}
Use HealthKit to enable your iOS and watchOS apps to work with the Apple Health app.
Post
Replies
Boosts
Views
Activity
Heya,
I'm currently building out my own application for tracking my health information, and I'm hoping to collect my historical data from Apple Health.
Sadly, it would appear that certain things I wish to export don't appear in the export.xml file.
Some of the things that I would expect to find in the export.xml file, that do not currently appear, are as follows:
More data about my medications, currently I can only export a list of my medications, its not possible to export data such as when what medication was taken.
Logged emotions; there is currently no support for this (that I can find).
Would appreciate some insight into this.
Hi there!
I've using the betas for a month now, and 18.1 at the moment.
I've always had my Health App crashing once I tap on "Treatments".
Is it a know bug? Is it working properly on your phones?
I've already sent a feedback, but got not answer yet.
Thanks ^^
must add the same happens on my iPad using beta version as well
Hi! I've added the code of the multidevice workout app from Apple to my app and I found some issues that I cannot see on the sample app.
In my app, to pause or end the workout from the watch, the iOS companion app has to be opened or at least on background, but never closed.
What I'm doing wrong?
Hi All,
I am posting this to get some help on fetching Water intake data from Health Kit.
I have done (following a similar approach, and perfectly working) the fetch of the user weight, but for the water, somehow, I always receive back 0 samples.
I went to the Health App, added few entries (in different days) for the water intake, under the food sections.
Then, I use the following snippet to read the values, but I always have 0 values back.
What I am doing wrong?
let type = HKQuantityType(.dietaryWater)
let samplePredicate = HKSamplePredicate.sample(type: type, predicate: nil)
// Create the descriptor.
let descriptor = HKSampleQueryDescriptor(
predicates: [samplePredicate],
sortDescriptors: [SortDescriptor(\.endDate, order: .reverse)])
let results = try await descriptor.result(for: hkHealthStore)
The results variable is always 0 elements.
What I am doing wrong?
PS: The permissions are checked and correctly given for this: HKQuantityType(.dietaryWater)
Hello!
My sleep process isn't recorded with iPhone only (without wearable device) on iOS 18. On previous iOS versions it was recorded but now it doesn't work.
I compare iOS 17 and iOS 18 Beta and I see the difference that in Full Schedule was deleted tumbler "Track Time in Bed with iPhone" that helped to track sleep process without wearable device (I found it here: Health app -> Browse -> Sleep -> Your schedule block and tap on "Full Schedule & Options" -> Scroll to the bottom).
I didn't find any information from Apple about this changes in change log.
And one more time: I don't use Apple Watch or any wearable device.
Do you have any information about sleep tracking with iPhone only? Can I track sleep process only with iPhone?
On watchOS 11 when starting a workout session a widget appears automatically on the smart stack showing the pause or resume button.
It´s a great feature, but my problem is that the duration is not showed correctly because the prepare phase of the workout and the pause / resume events are not taken into account calculating the duration.
In my project I don´t use the workout builder. I have made a sample project with workout builder and there the duration is shown correctly.
It would be great if this automatically appearing widget would also show the time correctly in case the workout builder is not used (prepare phase and pause resume events considered, otherwise it looks like a bug).
Is there any way to opt out of this automatically appearing widget or could this be fixed? Any comments from an Apple engineer on this?
My iOS app has a correctly configured HealthKit integration. It successfully delivers all samples and data to HealthKit. For every workout sent to HealthKit, I can see the duration, workout name, calories, and other details.
However, the app icon is missing. My project uses the Single Size setting for the app icon in the XCAssets folder. The app is available in the App Store in some regions. What can I do to fix this issue?
The problem persists regardless of whether the device is running iOS 17 or 18.
Are there any limitations on how long iOS will continue delivering background updates from HealthKit to the app? Will deliveries be suspended if the user stops opening the app for a few days, a month, or longer?
Hello, I am trying to build a features where I want to monitor a user's biking workout session metrics like the current speed, average speed and distance travelled. I want to get these metrics as the user is actively doing a workout session in the Workouts app of the apple watch. Is it possible? Or it is not possible to get data from an active workout session from the workouts app.
Hey folks, a couple of questions regarding WorkoutKit:
What happened to validation errors? They are mentioned in the WWDC23 video, but no longer are present in the API. It seems a fatal error is thrown if the workout fails validation (for example setting a negative distance in a workout goal).
What is the logic of the WorkoutScheduler, if we try to add more workouts than is allowed? If the limit is 50, what happens when we try to add a 51st? Are workouts de-queued based on date or anything? API documentation is very sparse
Do completed workouts and workouts with a scheduled date in the past stay in the WorkoutScheduler? Are we responsible for removing these? I guess my overall question regarding the WorkoutScheduler is, what are we responsible for managing and what is handled gracefully for us.
None of these answers seem to be openly available, but if anyone know anecdotally or even better from the WorkoutKit team, I'd be very grateful!
Thanks!
We are integrating Apple Health step data into our mobile application, Diyetkolik. However, we have received feedback from our users indicating that the step data appears to be significantly higher than expected. After conducting thorough research, we discovered that users who wear a smartwatch are experiencing step data duplication. Both the smartwatch and the phone's step data are being collected and combined, leading to inflated step counts in our application.
We kindly request your assistance in addressing the following issues:
How can we differentiate between step data from the smartwatch and the phone to avoid duplication?
Are there best practices or specific APIs we should use to filter and manage step data more accurately?
Can you provide guidance on how to implement a solution that ensures accurate step count data for users wearing multiple devices?
We appreciate your support in resolving this matter to enhance the accuracy of our application and improve user experience.
During WatchOS 10 dev betas and now into 11 dev betas, I am still seeing were stands are not being detected. What I do not know is if the steps are detected. But here is the situation.
Today:
I was going on some wiring outside and in the basement.
I was clearly up and moving around for over an hour.
I can see on my camera's I went outside at 15:50, came back in at 16:18. Then went to my basement and was working down there from 16:19 until 16:30. After that cleaned up my mess. So I was up and down stairs and without a doubt standing. At 16:50 I got the reminder to stand.
Other cases:
1: I get home from work about XX:10 . I have to walk about 50 ft from my garage to my house, up stairs, take the dog out, make dinner, and finally get my chair to eat and at XX:50 I get the reminder.
2: I'm at work, I'm going to get lunch and I have to walk pretty far and again at XX:50 I get the reminder. This is very rare, but it has happened.
Now, in a odd twist. I get up in the morning at XX:50, I have 10 steps to the bathroom, and I manage to get that hourly stand.
I have installed IOS18 and WatchOS11 Beta 3 already... all complications sent to clock (usign FACER app) is not showing up... they all appears DISABLED.
doesnt matter what face watch i use.., its all disabled.
Any help on it please????
Dear Apple Team,
QSFA app belongs to the Ministry of Sports and Youth in Qatar and there's a feature which will get the step count from the Apple health kit.
Our issue that while the app is closed or on the background, we are not getting the steps count for the users and we need the steps data to keep sending notifications based on the steps as motivations to the users to keep walking and do sport.
Please give us a suggestion or solution on how we can retrieve the steps data as we have limitations on this.
Hello,
I am writing workout data into HealthKit using the HKWorkoutBuilder API for specific types of workouts (e.g. Cycling) in particular various time series data for power, speed, etc.. but I am unable to see the average values for these quantities on the workout summary page in the Apple Fitness app ? (I am only able to see the graph data in the show more / workout details) anything specific to be done in order to have the data shown in the main summary ?
As the HealthKit is available for VisionOS, but there is no Health app. When will the Health app be available in VisionOS?
This has long been a frustration of mine on Apple Watch, and I've brought it up at WWDC labs every year to no avail but while the limitation on the Apple Watch to only be able to query 7 days of HealthKit data may have made sense early in the AW's lifetime for battery preservation etc., it really no longer makes sense in modern AW development.
Especially not with stand alone watch apps, as a developer I am prohibited from building the same experience on the Apple Watch that I can in an iPhone app. For example, my app looks at your current health metrics and compares them to your 60 day baseline to identify any deviations from your normal ranges. I cannot create the same experience on the watch using purely HealthKit queries, and am limited to using either iCloud or Watch Connectivity which have their own drawbacks and are not an option for a stand alone watch app.
Can we finally expand the length of HealthKit queries the AW can make so that we can build the same powerful experience on the watch that we can on iPhone?
Thank you!
Gary
See also Feedback FB7649612 (from April 2020).
Hi everyone,
With iOS 18 and watchOS 11 it is possible to pause your activity rings so that a streak is not broken when you are ill or something like that.
When we request data from the HealthStore, is there a way to know that a user has set this option for a particular date or period?
Or will the data for that date just return nil for all 3 ring values or even skip the day in the dataset?
I have an app in which I also keep track of people's streaks, so it would really useful to know if the activity rings are paused.
Thanks in advance!
It's fairly well know and stated that the Apple Health / HealthKit data store is unavailable when iPhone is locked.
Since Lock Screen Widgets were introduced there's been a feature parity mismatch with Apple's own Fitness app which is able to display updating Activity Rings on the Lock Screen. Third party apps cannot do this and have to rely unlocking their device to then trigger an update. This means they often display stale and wrong Health data.
With the release of iOS 18 beta, I see no changes to this... Is there anything I've missed?
Currently for requesting the Timeline Updates on my Widget I have to just keep requesting updates as often as possible and hope that each time the iPhone might be unlocked.... This is inefficient and a waste of device resources. Even a Widget timeline reload API that let the developer say "Only call update if iPhone unlocked" would be useful.