Use HealthKit to enable your iOS and watchOS apps to work with the Apple Health app.

All subtopics
Posts under Health and Fitness topic

Post

Replies

Boosts

Views

Activity

Workout Effort Scores
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.
4
0
2.4k
Oct ’24
Issue with Air play since new update iOs18 (apple fitness App)
Can’t start fitness video with my iPhone on my tv since new update 18.1. Air play is connecting I see the countdown then the dots rolling but nothing happens and I end up receiving a « can’t read video » message. I’m using an iphone 16 pro max, an apple watch ultra (1st gen) and an apple tv HD (A1625 model). I have almost the same issue with a more recent Apple TV, but on that one it’s just painfully long before the video starts but it does start eventually (just taking much longer than it used to). That some tv is an A2843 model (apple tv 4k 3rd gen). Has anyone else had this issue?
1
0
882
Oct ’24
Missing manual - Training Load, .estimatedWorkoutEffortScore, .workoutEffortScore - Where are the Apple RPE CR-10 scale docs?
Apple is using the RPE scale for workout effort scores. This stands for the Rate of Perceived Exertion. They're specifically using the CR-10 scale, at least from what I can tell by saving values to HealthKit. They only accept value between 0 and 10. Has anyone been able to find a scientific or academic paper on how they have chosen their different effort breakouts? Right from the Fitness app on iPhone and Activity app on Apple Watch: 1-3 Easy 4-6 Moderate 7-8 Hard 9-10 All Out There is zero documentation on these new types, which makes it difficult for workout recording apps to properly and appropriately save this new data type. Sure, we can use the Apple apps as a reference, but since there isn't a built-in Apple SwiftUI sheet to present this data, and no references to academia to point our users to, our solutions would just look the same. FB15315876 - Documentation / HealthKit: Publish documentation about .workoutEffortScore and .estimatedWorkoutEffortScore FB15316109 - Documentation / HealthKit: Add documentation to .estimatedWorkoutEffortScore and .workoutEffortScore that you can't save those samples via the save API and that they must be related and let that API save the sample FB15316251 - Documentation / HealthKit: Add documentation for acceptible values of .estimatedWorkoutEffortScore and .workoutEffortScore - don't rely on a runtime error! Apple missed making an enum for all third party developers this year.
0
1
819
Oct ’24
How to add "Estimated Time in Each Heart Rate Zone" info to my custom HKWorkout when viewed in Apple Fitness app?
Hello, I’m currently developing a fitness app for watchOS that lets a user to manually set a desired heart rate target zone (enter numbers representing the lower and upper boundaries) and start a workout (right now it’s only “Other” type). After that my app monitors user’s heart rate and alerts them when they’re out of zone. When user ends the workout, the info about this workout appears on “Fitness” iOS app, and user can see the workout data like Workout Time, Active and Total Calories, Avg. Heart Rate. Also user can see Heart Rate chart with info how their heart rate was changing during a workout (see the Figure 1). Now to the question. When user clicks “Show More” button above the Heart Rate chart, they can see the same Heart Rate chart and another one, with Post-Workout Heart Rate (see the Figure 2). But there is no “Estimated time in each heart rate zone” as one can see in the workout’s details that were recorded from Apple’s workout (watchOS “Workout” app, for a workout of “Other” type as well). Please see the Figure 3. The question is: is it possible to add “Estimated time in each heart rate zone” to workout recorded via my third-party app so it would look like on the Figure 3 in "Fitness" iOS app, and if it's possible, what steps should I undertake to implement this ? Thanks in advance! I posted the screenshots in the replies to the post, because otherwise I was not able to submit a post ("sensitive language" warning, I suspect it's because of the ids in the attached screenshot's urls)
2
0
1.3k
Oct ’24
visionOS App Not Receiving Latest Heart Rate Data from HealthKit
Hello everyone, I'm developing an app for visionOS that utilizes HealthKit to query heart rate data. However, I'm encountering an issue where the app doesn't retrieve the latest heart rate values. Specifically, it fails to get live heart rate data even after the data has been saved to the Health app. The readings my app displays are outdated and do not match the current values shown in the Health app. Here's what I've tried so far: Fetching Heart Rate Samples: Used HKSampleQuery and HKAnchoredObjectQuery to fetch the most recent heart rate samples. Despite this, the data retrieved is still not up-to-date. Checking Permissions: Ensured that all necessary HealthKit permissions are granted. The app has authorization to read heart rate data and write workout data. My questions are: Is there a known issue or limitation with HealthKit on visionOS that prevents apps from accessing the latest heart rate data? Are there additional steps or configurations required to access live heart rate data in visionOS apps? Has anyone successfully implemented live heart rate monitoring on visionOS, and if so, could you share how you achieved it?
0
0
585
Sep ’24
HealthKit bugs related to new workout effort score - heart rate samples take forever to fetch, Health app displays invalid data
I am encountering issues on my device running iOS 18 that fetching heart rate samples associated to a given workout is very slow. Like 10+ seconds slow. This is unacceptable and unexpected. In producing a video to attach to a feedback, I also observed that Apple Health app displays incorrect information if a workout effort score is associated to a workout. In this image, you can see the Health app bug: Total Resting Energy != Estimated Workout Effort Score Here is the same workout after I delete the workout effort score using the Apple Health app: Can anyone else see if attempting to view 'heart rate' data within the workout summary in Apple Health is unbearably slow if that workout also has an effort score associated? My steps: Record workout (Apple Activity app on watchOS) Associate effort score View the workout on Apple Health (iOS) Attempt to view it's heart rate samples Observe very slow loading times Observe the incorrect cell label and value and disappearance of resting energy cell data Remove/disassociate the effort score from the workout by tapping the workout effort row, and swipe to delete the value. Navigate back, navigate back, and then go into the workout detail again At this time the UI fixes itself, but the loading of heart rate data is still super slow FB15269657 - HealthKit: Sample query to fetch heart rate samples associated to a workout is taking over 10 seconds - computing 'time in heart rate zone' FB15278790 - Health: Workout summary 'Total Resting Energy' label has value of 'Estimated Workout Effort Score' for a value, pushed view shows empty
0
0
835
Sep ’24
Wake-up detection with HealthKit
Hello HealthKit Experts & Enthusiasts! I am building an app called one sec which forces people to take a deep breath before they can use social media apps (it’s using Shortcuts Automations for that). One important feature of one sec is the Good Morning Countdown: For a specified time after waking up (e.g. 30mins) selected apps are blocked completely. This helps to start the day screen-free. They way it works is, the user grants access to read HKCategoryTypeIdentifier.sleepAnalysis data. I have implemented a HKObserverQuery and enableBackgroundDelivery in order to be informed whenever new HKCategoryTypeIdentifier.sleepAnalysis becomes available. I noticed that when I have my device connected to Xcode, this works as expected. However, when I quit the app and launch it from my Home Screen, my observer query is not informed about new sleep data (except when my app is running in foreground). Any ideas? Furthermore, I have noticed that sometimes sleep data is provided delayed to HealthKit, many minutes (sometimes even longer) after waking up, no sleep samples are to be found in the Health app. Of course, for my app it is crucial to get accurate + timely so apps can be blocked accordingly. Is this an issue that the Apple Watch first needs to send the samples to the phone? Thanks a lot for your help!
1
1
1k
Sep ’24
HKLiveWorkoutBuilder only reporting heart rate - No other measurements
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)") } } } } } }
6
0
1.3k
Sep ’24
recoverActiveWorkoutSession() inaccurate for paused sessions
When a workout session is being recovered, if it is paused, the elapsed time will be incorrect. It will seem like that workout never was paused. The recovery works fine if the workout was never paused. Steps to reproduce: Implement recoverActiveWorkoutSession Start workout Pause session and print the elapsed time Stop simulator / cause crash When recoverActiveWorkoutSession is called the elapsed time will not equal the elapsed time when the session was paused. Here is my implementation. I haven't seen any examples online. guard let recovered = try? await healthStore.recoverActiveWorkoutSession() else {return} self.session = recovered self.builder = recovered.associatedWorkoutBuilder() self.session?.delegate = self self.builder?.delegate = self self.builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: recovered.workoutConfiguration) self.sessionState = recovered.state
1
0
989
Sep ’24
WatchOS Fall Detection Consequences
My team and I are working on an app for a private emergency helpline. Now as far as I understand the (sparse) API documentation for fall detection, given the appropriate entitlement, the following happens upon a detected fall: The Standard UI will be opened with the options to a) call SOS b) acknowledge the fall but state that you're fine though, c) deny the fall, and (implicitly after 60 seconds on inactivity) call SOS because you didn't react. All fall detection apps will then receive a bit of background time and get the func fallDetectionManager(CMFallDetectionManager, didDetect: CMFallDetectionEvent, completionHandler: () -> Void) called with the appropriate event value. Now that's all good and it sounds like the custom fall detection is additive to the standard system. But but why is there something like that in the entitlement request form sheet: For any emergency calling features that you do not provide, explain any mitigations you use to make sure the user receives emergency services support that’s as close as possible to what they’d receive had they placed an emergency call natively. This sounds like our app would rather be a drop-in to the standard SOS service ­– in contrast to being additive and also in contrast to what the API documentation infers. Am I misunderstanding something?
1
0
792
Sep ’24
Workouts, activity rings, samples and more not syncing across devices running iOS 18 RC and watchOS 11 RC
I noticed last night that workouts I have been recording on my main carry device running 17.6.x have not been syncing to my beta devices running iOS 18 RC, iPadOS 18 RC and watchOS 11 RC. All devices are using the same Apple Account and I have iCloud enabled for Health data. The iPad running the RC has the syncing enabled in Profile. Is anyone else experiencing health data not propagating to the 18.x devices? Some of data exists on all devices but not all. For good measure I left the device unlocked on the health app last night for a long period of time to let it do its thing. This morning the data still hadn't propagated. I disabled and reenabled the synchronization on my iPad having chosen to delete all samples when disabling it. Hopefully all of my data dating back to the first Apple Watch in 2014 restores. FWIW my data set according to iCloud settings my health dataset is just shy of 650 MB. FB15102443 - Health / HealthKit: Workouts, activity rings, sample data, and more not syncing via iCloud to 18 RC device
0
0
767
Sep ’24
BGTaskScheduler with
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 }
2
0
915
Aug ’24
Apple Health `export.zip` doesn't include several important data points.
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.
1
0
900
Aug ’24
Unable to fetch Water data from HealthKit
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)
1
0
785
Aug ’24
Missing app icon in the Fitness app
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.
4
2
869
Aug ’24
watchOS 11 beta 5 - Problem workout duration wrong on automatically appearing widget
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?
1
0
741
Aug ’24
Workout Effort Scores
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.
Replies
4
Boosts
0
Views
2.4k
Activity
Oct ’24
Issue with Air play since new update iOs18 (apple fitness App)
Can’t start fitness video with my iPhone on my tv since new update 18.1. Air play is connecting I see the countdown then the dots rolling but nothing happens and I end up receiving a « can’t read video » message. I’m using an iphone 16 pro max, an apple watch ultra (1st gen) and an apple tv HD (A1625 model). I have almost the same issue with a more recent Apple TV, but on that one it’s just painfully long before the video starts but it does start eventually (just taking much longer than it used to). That some tv is an A2843 model (apple tv 4k 3rd gen). Has anyone else had this issue?
Replies
1
Boosts
0
Views
882
Activity
Oct ’24
Missing manual - Training Load, .estimatedWorkoutEffortScore, .workoutEffortScore - Where are the Apple RPE CR-10 scale docs?
Apple is using the RPE scale for workout effort scores. This stands for the Rate of Perceived Exertion. They're specifically using the CR-10 scale, at least from what I can tell by saving values to HealthKit. They only accept value between 0 and 10. Has anyone been able to find a scientific or academic paper on how they have chosen their different effort breakouts? Right from the Fitness app on iPhone and Activity app on Apple Watch: 1-3 Easy 4-6 Moderate 7-8 Hard 9-10 All Out There is zero documentation on these new types, which makes it difficult for workout recording apps to properly and appropriately save this new data type. Sure, we can use the Apple apps as a reference, but since there isn't a built-in Apple SwiftUI sheet to present this data, and no references to academia to point our users to, our solutions would just look the same. FB15315876 - Documentation / HealthKit: Publish documentation about .workoutEffortScore and .estimatedWorkoutEffortScore FB15316109 - Documentation / HealthKit: Add documentation to .estimatedWorkoutEffortScore and .workoutEffortScore that you can't save those samples via the save API and that they must be related and let that API save the sample FB15316251 - Documentation / HealthKit: Add documentation for acceptible values of .estimatedWorkoutEffortScore and .workoutEffortScore - don't rely on a runtime error! Apple missed making an enum for all third party developers this year.
Replies
0
Boosts
1
Views
819
Activity
Oct ’24
How to add "Estimated Time in Each Heart Rate Zone" info to my custom HKWorkout when viewed in Apple Fitness app?
Hello, I’m currently developing a fitness app for watchOS that lets a user to manually set a desired heart rate target zone (enter numbers representing the lower and upper boundaries) and start a workout (right now it’s only “Other” type). After that my app monitors user’s heart rate and alerts them when they’re out of zone. When user ends the workout, the info about this workout appears on “Fitness” iOS app, and user can see the workout data like Workout Time, Active and Total Calories, Avg. Heart Rate. Also user can see Heart Rate chart with info how their heart rate was changing during a workout (see the Figure 1). Now to the question. When user clicks “Show More” button above the Heart Rate chart, they can see the same Heart Rate chart and another one, with Post-Workout Heart Rate (see the Figure 2). But there is no “Estimated time in each heart rate zone” as one can see in the workout’s details that were recorded from Apple’s workout (watchOS “Workout” app, for a workout of “Other” type as well). Please see the Figure 3. The question is: is it possible to add “Estimated time in each heart rate zone” to workout recorded via my third-party app so it would look like on the Figure 3 in "Fitness" iOS app, and if it's possible, what steps should I undertake to implement this ? Thanks in advance! I posted the screenshots in the replies to the post, because otherwise I was not able to submit a post ("sensitive language" warning, I suspect it's because of the ids in the attached screenshot's urls)
Replies
2
Boosts
0
Views
1.3k
Activity
Oct ’24
How to read Apple iOS 16 Heart Rate Zones from HealthKit
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
Replies
3
Boosts
2
Views
2.4k
Activity
Oct ’24
How can I turn on the apnea notification?
There's no option to help me turn it on in my iPhone 16 Pro Max MYW43LL/A (iOS 18.1 developer beta) and Apple Watch Series 10 MWX13LW/A (watchOS 11 Developer Beta).
Replies
1
Boosts
1
Views
580
Activity
Sep ’24
visionOS App Not Receiving Latest Heart Rate Data from HealthKit
Hello everyone, I'm developing an app for visionOS that utilizes HealthKit to query heart rate data. However, I'm encountering an issue where the app doesn't retrieve the latest heart rate values. Specifically, it fails to get live heart rate data even after the data has been saved to the Health app. The readings my app displays are outdated and do not match the current values shown in the Health app. Here's what I've tried so far: Fetching Heart Rate Samples: Used HKSampleQuery and HKAnchoredObjectQuery to fetch the most recent heart rate samples. Despite this, the data retrieved is still not up-to-date. Checking Permissions: Ensured that all necessary HealthKit permissions are granted. The app has authorization to read heart rate data and write workout data. My questions are: Is there a known issue or limitation with HealthKit on visionOS that prevents apps from accessing the latest heart rate data? Are there additional steps or configurations required to access live heart rate data in visionOS apps? Has anyone successfully implemented live heart rate monitoring on visionOS, and if so, could you share how you achieved it?
Replies
0
Boosts
0
Views
585
Activity
Sep ’24
HealthKit bugs related to new workout effort score - heart rate samples take forever to fetch, Health app displays invalid data
I am encountering issues on my device running iOS 18 that fetching heart rate samples associated to a given workout is very slow. Like 10+ seconds slow. This is unacceptable and unexpected. In producing a video to attach to a feedback, I also observed that Apple Health app displays incorrect information if a workout effort score is associated to a workout. In this image, you can see the Health app bug: Total Resting Energy != Estimated Workout Effort Score Here is the same workout after I delete the workout effort score using the Apple Health app: Can anyone else see if attempting to view 'heart rate' data within the workout summary in Apple Health is unbearably slow if that workout also has an effort score associated? My steps: Record workout (Apple Activity app on watchOS) Associate effort score View the workout on Apple Health (iOS) Attempt to view it's heart rate samples Observe very slow loading times Observe the incorrect cell label and value and disappearance of resting energy cell data Remove/disassociate the effort score from the workout by tapping the workout effort row, and swipe to delete the value. Navigate back, navigate back, and then go into the workout detail again At this time the UI fixes itself, but the loading of heart rate data is still super slow FB15269657 - HealthKit: Sample query to fetch heart rate samples associated to a workout is taking over 10 seconds - computing 'time in heart rate zone' FB15278790 - Health: Workout summary 'Total Resting Energy' label has value of 'Estimated Workout Effort Score' for a value, pushed view shows empty
Replies
0
Boosts
0
Views
835
Activity
Sep ’24
Wake-up detection with HealthKit
Hello HealthKit Experts & Enthusiasts! I am building an app called one sec which forces people to take a deep breath before they can use social media apps (it’s using Shortcuts Automations for that). One important feature of one sec is the Good Morning Countdown: For a specified time after waking up (e.g. 30mins) selected apps are blocked completely. This helps to start the day screen-free. They way it works is, the user grants access to read HKCategoryTypeIdentifier.sleepAnalysis data. I have implemented a HKObserverQuery and enableBackgroundDelivery in order to be informed whenever new HKCategoryTypeIdentifier.sleepAnalysis becomes available. I noticed that when I have my device connected to Xcode, this works as expected. However, when I quit the app and launch it from my Home Screen, my observer query is not informed about new sleep data (except when my app is running in foreground). Any ideas? Furthermore, I have noticed that sometimes sleep data is provided delayed to HealthKit, many minutes (sometimes even longer) after waking up, no sleep samples are to be found in the Health app. Of course, for my app it is crucial to get accurate + timely so apps can be blocked accordingly. Is this an issue that the Apple Watch first needs to send the samples to the phone? Thanks a lot for your help!
Replies
1
Boosts
1
Views
1k
Activity
Sep ’24
HKLiveWorkoutBuilder only reporting heart rate - No other measurements
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)") } } } } } }
Replies
6
Boosts
0
Views
1.3k
Activity
Sep ’24
recoverActiveWorkoutSession() inaccurate for paused sessions
When a workout session is being recovered, if it is paused, the elapsed time will be incorrect. It will seem like that workout never was paused. The recovery works fine if the workout was never paused. Steps to reproduce: Implement recoverActiveWorkoutSession Start workout Pause session and print the elapsed time Stop simulator / cause crash When recoverActiveWorkoutSession is called the elapsed time will not equal the elapsed time when the session was paused. Here is my implementation. I haven't seen any examples online. guard let recovered = try? await healthStore.recoverActiveWorkoutSession() else {return} self.session = recovered self.builder = recovered.associatedWorkoutBuilder() self.session?.delegate = self self.builder?.delegate = self self.builder?.dataSource = HKLiveWorkoutDataSource(healthStore: healthStore, workoutConfiguration: recovered.workoutConfiguration) self.sessionState = recovered.state
Replies
1
Boosts
0
Views
989
Activity
Sep ’24
WatchOS Fall Detection Consequences
My team and I are working on an app for a private emergency helpline. Now as far as I understand the (sparse) API documentation for fall detection, given the appropriate entitlement, the following happens upon a detected fall: The Standard UI will be opened with the options to a) call SOS b) acknowledge the fall but state that you're fine though, c) deny the fall, and (implicitly after 60 seconds on inactivity) call SOS because you didn't react. All fall detection apps will then receive a bit of background time and get the func fallDetectionManager(CMFallDetectionManager, didDetect: CMFallDetectionEvent, completionHandler: () -> Void) called with the appropriate event value. Now that's all good and it sounds like the custom fall detection is additive to the standard system. But but why is there something like that in the entitlement request form sheet: For any emergency calling features that you do not provide, explain any mitigations you use to make sure the user receives emergency services support that’s as close as possible to what they’d receive had they placed an emergency call natively. This sounds like our app would rather be a drop-in to the standard SOS service ­– in contrast to being additive and also in contrast to what the API documentation infers. Am I misunderstanding something?
Replies
1
Boosts
0
Views
792
Activity
Sep ’24
Workouts, activity rings, samples and more not syncing across devices running iOS 18 RC and watchOS 11 RC
I noticed last night that workouts I have been recording on my main carry device running 17.6.x have not been syncing to my beta devices running iOS 18 RC, iPadOS 18 RC and watchOS 11 RC. All devices are using the same Apple Account and I have iCloud enabled for Health data. The iPad running the RC has the syncing enabled in Profile. Is anyone else experiencing health data not propagating to the 18.x devices? Some of data exists on all devices but not all. For good measure I left the device unlocked on the health app last night for a long period of time to let it do its thing. This morning the data still hadn't propagated. I disabled and reenabled the synchronization on my iPad having chosen to delete all samples when disabling it. Hopefully all of my data dating back to the first Apple Watch in 2014 restores. FWIW my data set according to iCloud settings my health dataset is just shy of 650 MB. FB15102443 - Health / HealthKit: Workouts, activity rings, sample data, and more not syncing via iCloud to 18 RC device
Replies
0
Boosts
0
Views
767
Activity
Sep ’24
BGTaskScheduler with
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 }
Replies
2
Boosts
0
Views
915
Activity
Aug ’24
Apple Health `export.zip` doesn't include several important data points.
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.
Replies
1
Boosts
0
Views
900
Activity
Aug ’24
Health App crash when clicking on "Treatments"
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
Replies
2
Boosts
0
Views
627
Activity
Aug ’24
Building a multidevice workout app issue
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?
Replies
2
Boosts
0
Views
874
Activity
Aug ’24
Unable to fetch Water data from HealthKit
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)
Replies
1
Boosts
0
Views
785
Activity
Aug ’24
Missing app icon in the Fitness app
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.
Replies
4
Boosts
2
Views
869
Activity
Aug ’24
watchOS 11 beta 5 - Problem workout duration wrong on automatically appearing widget
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?
Replies
1
Boosts
0
Views
741
Activity
Aug ’24