Hi,
I've had trouble for a while now with HealthKit giving me different values if I make the request on iOS and WatchOS.
I am using the exact same method on both with the same parameters but I get vast differences in the results.
The code I am using to call HealthKit on both devices is:
let dateRange = HKQuery.predicateForSamples(withStart: Date().removeMonths(numberOfMonths: 1), end: Date().endOfDay())
let predicate: NSPredicate
predicate = NSCompoundPredicate(type: .and, subpredicates: [dateRange])
let query = HKStatisticsQuery(quantityType: HKQuantityType(.stepCount), quantitySamplePredicate: predicate, options: .cumulativeSum) { _, result, error in
if error != nil {
//print("Error fetching step count, or there is no data: \(error.localizedDescription), \(startDate) -> \(endDate)")
onComplete(0)
return
}
if let result, let sum = result.sumQuantity() {
let stepCount = sum.doubleValue(for: HKUnit.count())
DispatchQueue.main.async {
onComplete(Int(stepCount))
}
}
}
healthStore.execute(query)
}
Health & Fitness
RSS for tagExplore the technical aspects of health and fitness features, including sensor data acquisition, health data processing, and integration with the HealthKit framework.
Post
Replies
Boosts
Views
Activity
I want to use the Apple Healthkit data to recommend personalised insurance. Is this allowed? As I have read in the documentation that the Apple Healthkit data can only be used for fitness and health purposes. Anyone knows what is meant / scope of "fitness and health purposes"? Will personalised insurance as per health data be allowed under this category?
I've been trying to figure out what the bare minimum is required for HKWorkoutBuilder to create a workout that adds time the appleExerciseTime. I couldn't find the documentation for this. This is my code so far.
func createWorkoutSample(
expectedActiveEnergyData: [Double],
expectedExerciseMinutesData: [Double],
calendar: Calendar,
startDate: Date
) async throws -> [HKSample] {
var testData: [HKSample] = []
let workoutConfiguration = HKWorkoutConfiguration()
workoutConfiguration.activityType = .running
workoutConfiguration.locationType = .outdoor
let results = try await withThrowingTaskGroup(of: HKSample?.self) { group in
for (index) in 0..<expectedActiveEnergyData.count {
guard let date = calendar.date(byAdding: .day, value: index, to: startDate) else {
continue
}
group.addTask {
let builder = HKWorkoutBuilder(
healthStore: self.manager.healthStore,
configuration: workoutConfiguration,
device: .local()
)
let endDate = date.addingTimeInterval(expectedExerciseMinutesData[index] * 60)
try await builder.beginCollection(at: date)
let energyType = HKQuantityType.quantityType(
forIdentifier: .activeEnergyBurned
)!
let energyQuantity = HKQuantity(
unit: HKUnit.kilocalorie(),
doubleValue: expectedActiveEnergyData[index]
)
let energySample = HKQuantitySample(
type: energyType,
quantity: energyQuantity,
start: date,
end: endDate
)
return try await withCheckedThrowingContinuation { continuation in
builder.add([energySample]) { (success, error) in
if let error = error {
continuation.resume(throwing: error)
return
}
builder.endCollection(withEnd: endDate) { (success, error) in
if let error = error {
continuation.resume(throwing: error)
return
}
builder.finishWorkout { (workout, error) in
if let error = error {
continuation.resume(throwing: error)
return
}
continuation.resume(returning: workout)
}
}
}
}
}
}
for try await workout in group {
if let workout = workout {
testData.append(workout)
} else {
print("Skipping nil workout result.")
}
}
return testData
}
print("Total samples created: \(results.count)")
return results
}
When I query appleExerciseTime, there are no results. I've looked at the HKWorkoutBuilder documentation, and most of the information expands on adding samples related to the deprecated HKWorkout.
I have a workout app which I am testing on device currently via TestFlight.
The generated workout (tennis and indoor) shows in the fitness app with correct HR and duration.
However, when I go to my Strava app, it does not show in the list of workouts for importing. (note, activities tracked using the regular tennis mode on the Apple Watch show fine)
I have also concurrently reached out to Strava support to see if there's anything they can offer support for.
However, does anybody here have any knowledge/experience of the requirement? Or whether this is a limitation of an application deployed via TestFlight?
I have a terrible feeling I am chasing ghosts, and it may be a TestFlight limitation for exporting workouts?
Thanks
Good afternoon,
I am working on a workout tracking app. So far everything is working as expected. However, I note that when my workout saves and is visible within the Fitness App, the workout duration is displayed rather than the kCal burned.
What changes are required to be made in order for this to display the kCal in the list of workouts in Fitness rather than duration?
For reference https://developer.apple.com/videos/play/wwdc2021/10009 this was my reference source for workout functionality.
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?
We have working code to fetch step data from HealthKit after requesting the necessary permissions. However, we’ve encountered an issue specific to one device, the iPhone 16 Pro Max. When querying the data, we do not receive a response, and the code enters an infinite loading state without completing the request.
The user who is facing this issue has tried logging in on another device, and it works fine. On the problematic device (iPhone 16 Pro Max), the request does not complete.
For reference, I’ve included the code below. Resolving this issue is crucial, so we would appreciate any guidance on what steps we can take to troubleshoot or resolve the problem on this specific device.
Please note that the device has granted permission to access HealthKit data.
static let healthStore = HKHealthStore()
static func limitReadFromHealthKitBetweenDates(fromDate: Date, toDate: Date = Date(), completion: @escaping ([HKStatistics]) -> Void) {
guard let stepsQuantityType = HKQuantityType.quantityType(forIdentifier: .stepCount) else { return }
let ignoreUserEntered = HKQuery.predicateForObjects(withMetadataKey: HKMetadataKeyWasUserEntered, operatorType: .notEqualTo, value: true)
let now = toDate
var interval = DateComponents()
interval.day = 1
var calendar = Calendar.current
calendar.locale = Locale(identifier: "en_US_POSIX")
var anchorComponents = calendar.dateComponents([.day, .month, .year], from: now)
anchorComponents.hour = 0
let anchorDate = calendar.date(from: anchorComponents) ?? Date()
let query = HKStatisticsCollectionQuery(quantityType: stepsQuantityType,
quantitySamplePredicate: ignoreUserEntered,
options: [.cumulativeSum],
anchorDate: anchorDate,
intervalComponents: interval)
query.initialResultsHandler = { _, results, error in
guard let results = results else {
print("Error returned from resultHandler: \(String(describing: error?.localizedDescription))")
return
}
print(results)
var statisticsArray: [HKStatistics] = []
results.enumerateStatistics(from: fromDate, to: now) { statistics, _ in
statisticsArray.append(statistics)
if statistics.endDate.getddmmyyyyslashGMT == now.getddmmyyyyslashGMT {
completion(statisticsArray)
}
}
}
healthStore.execute(query)
}
Please note that the code works on all devices except the problematic one. Could you please guide me on the next steps to resolve this issue?
I am building a watchOS app with iOS companion app.
The watch app needs to track the heart rate during the night or while user is sleeping. And the desired frequency of measurement is 0.2Hz (every 5 seconds)
For this I am using the HKWorkout mode with mindAndBody session.
While it works fine, One of the main issue is: after about 6-7 hours of usage, the battery on the watch drains between 40% (Series 9) and 100% (series 7, I think)
My questions:
Are there any other option to track user's heart rate without workout, while the app could be in background?
Another side effect of this workout mode is, Even if we choose not to save the workout in HealthKit, the Activity rings gets populated by this mindAndBody session, which makes it when the user is waking up, the bar is already full, This is not desired.
Is there any option to specify for ActivityRing skips this?
Highly appreciate any help in advance.
Cheers - Prakash
Hello, we want to re-create these graphs and use the raw data for analysis.
We are getting aggregated elevation, heath rate, and pace data, but need to locate the specifics to create these graphs.
Thank you
As a user, there are times when I don't wear my sleep tracker to bed, but I nonetheless want to record my sleep times.
Apple Health supports this with the "Add Data" feature, but it's not possible to provide a time zone in the form.
Then as a developer, user-added sleep samples are missing time zone information.
I would expect that the time zone is requested within the Add Data form.
Without this information provided at input time, downstream applications are forced to infer the time zone ourselves, leading to potentially buggy or unintuitive behavior.
https://support.apple.com/zh-cn/104959
Our application provides car insurance services. Does Apple have any API related to car accident detection exposed to developers? We want to do something when an iPhone detects a car accident
good morning every one, hopefully this is the right place where to speak.
I am not a developer and I am not familiar with and programming.
I am a simple apple user and happend to me that my diving watch died few weeks ago. Since then I am using Apple Watch Ultra to free dive and spare fishing.
Honestly we few small modifications this watch can take the lead over Garmin and Suunto that at the moment are the two best watch on the market for this specific area.
will it be possible to give some feedbacks and develop the app?
many Thanks
Mickey
I'm encountering an issue with HealthKit permissions and would appreciate some guidance:
In my app's previous version, I granted write permissions for HKObjectType.workoutType() via the WatchKitExtension. Now, in the upcoming version, I'm trying to request read permissions for both HKObjectType.workoutType() and HKSeriesType.workoutRoute() via the iOS app.
However, after granting access:
The read permissions for Workout and Workout Route don't show up under Settings -> Health -> Data and Access -> [My App].
The Workout Route permission status remains notDetermined, even though I selected "Allow" when prompted.
Interestingly, if I request the same permissions via the WatchKitExtension, everything works as expected, and the issue doesn't occur.
Has anyone experienced a similar issue or have insights into why this might be happening? Could it be related to requesting permissions from the iOS app instead of the WatchKitExtension?
It may have made sense in the early days of watchOS, but given the Apple Watch is now 10 years old and we have "Standalone" Apple Watch apps, it no longer makes sense to have this seemingly arbitrary limitation of only being able to query 7 days of data on the watch. I have an open feedback (FB7649612) from 2020 with no responses and ask this question every year at WWDC Developer labs. WHY must we still deal with this limitation which only causes other developers to store critical health data in iCloud or on their own servers in order to provide a robust stand alone watch experience on the Apple Watch. Even Apple themselves must either use a separate private API or use iCloud for the new Vitals app. How else can I escalate this request?
I want to get the barometric pressure reading from the built-in barometer to display it in my iOS app. When I use CMAltimeter.startRelativeAltitudeUpdates(), my app receives no relative altitude update events, which means I can't view the barometric pressure from the sensor (because that's only contained in CMAltitudeData, not CMAbsoluteAltitudeData. If I use CMAltimeter.startAbsoluteAltitudeUpdates(), I get absolute altitude update events every second or so. NSMotionUsageDescription is set.
I have tried the following things, all of which haven't worked:
Only calling startRelativeAltitudeUpdates() and not startAbsoluteAltitudeUpdates()
Calling CMSensorRecorder.recordAccelerometer(forDuration: 0.1), as suggested in this thread
Calling CMMotionActivityManager.queryActivityStarting(from: .now, to: .now, to: .main), as suggested here
Physically moving my iPhone up and down about 200 feet using an elevator; I see absolute altitude updates which are in line with what's expected, but still receive no relative altitude update events
Calling the same APIs in a watchOS app on an Apple Watch Series 10; I see much less frequent absolute altitude updates, and still no relative altitude updates
I know the barometer sensor is working, because when I move my iPhone up and down even a foot or two indoors, I see an immediate change in the absolute altitude reading that I know wouldn't come from GPS.
This example code, when run on my iPhone 16 Pro running iOS 18.1.1, prints updates started and then updating absolute every second, but doesn't print anything else. The absolute altitude, accuracy, and authentication status fields update (and the auth status shows 3, indicating .authorized), but the relative altitude and pressure fields remain as --.
struct ContentView: View {
@State private var relAlt: String = "--"
@State private var relPressure: String = "--"
@State private var absAlt: String = "--"
@State private var precision: String = "--"
@State private var accuracy: String = "--"
@State private var status: String = "--"
var body: some View {
VStack {
Text("Altitude: \(relAlt) m")
.font(.title3)
Text("Pressure: \(relPressure) kPa")
.font(.title3)
Text("Altitude (absolute): \(absAlt) m")
.font(.title3)
Text("Precision: \(precision) m")
.font(.title3)
Text("Accuracy: \(accuracy) m")
.font(.title3)
Text("Auth status: \(status)")
.font(.title3)
}
.padding()
.onAppear {
let altimeter = CMAltimeter()
startRelativeBarometerUpdates(with: altimeter)
startAbsoluteBarometerUpdates(with: altimeter)
status = CMAltimeter.authorizationStatus().rawValue.formatted()
print("updates started")
}
}
private func startRelativeBarometerUpdates(with altimeter: CMAltimeter) {
guard CMAltimeter.isRelativeAltitudeAvailable() else {
relAlt = "nope"
relPressure = "nope"
return
}
altimeter.startRelativeAltitudeUpdates(to: .main) { data, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
if let data = data {
print("updating relative")
relAlt = String(format: "%.2f", data.relativeAltitude.doubleValue)
relPressure = String(format: "%.2f", data.pressure.doubleValue)
} else {
print("no data relative")
}
}
}
private func startAbsoluteBarometerUpdates(with altimeter: CMAltimeter) {
guard CMAltimeter.isAbsoluteAltitudeAvailable() else {
absAlt = "nope"
print("no absolute available")
return
}
let altimeter = CMAltimeter()
altimeter.startAbsoluteAltitudeUpdates(to: .main) { data, error in
if let error = error {
print("Error: \(error.localizedDescription)")
return
}
if let data = data {
print("updating absolute")
absAlt = String(format: "%.2f", data.altitude)
precision = String(format: "%.2f", data.precision)
accuracy = String(format: "%.2f", data.accuracy)
}
}
}
}
Is this behavior expected? How can I trigger delivery of relative altitude updates to my app?
I started with the custom workout example from Apple. I was able to load the apps from my mac (xcode) to my iphone. I can run the apps on my iphone. I completed the authorization and reviewed the workout. I then uploaded the workout to the watch and it appeared to work. It never showed up on the watch. I tried restarting the watch and iPhone. I have. a second watch and I tried that. Nothing helped. IPhone 14 with ios 18.2. Watch is Series 6 with watch OS 11.2. I also tried it with the watch on the charger but no change. Workout Kit seems like a good idea, but not if you cannot get it on your watch. It seems very few people are using it as there is little info online.
Hi guys,
In WWDC23 session 10016: Build custom workouts with WorkoutKit , the presenters mentioned that a Workout Plan can be exported to a JSON or binary file, and also showed a code snip:
let binaryRepresentation = try myCyclingWorkout.dataRepresentation(in: .compactBinary)
However in the current SDK, the property dataRepresentation can not be exported with a specific format, the base64EncodedString() result is unreadable.
Does anyone know how to export it as a JSON string now? Thanks very much.
Hi everyone, I need to display a Graph based on Screen-time of apps per hour, from 12Am to 11PM. Am able to get the screen-time data for whole day with each app's total screen-time value.
Am kind of confused how can I get the per hour screen-time of apps. I have applied filter of day
DeviceActivityFilter(
segment: .daily(
during: Calendar.current.dateInterval(
of: .day, for: .now
)!
),
users: .all,
devices: .init([.iPhone, .iPad])
)
Am also using this data to display apps with their usage just like Apple's Screen_time in settings.
I need to display exact same graph just like Apple's screen in phone settings for a Day.
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?
Hi,
there seems to be two methods to fetch data from HealthKit and calculate statistics on intervals of the data; HKStatisticsCollectionQuery and HKStatisticsCollectionQueryDescriptor.
I am currently using HKStatisticsCollectionQuery, but HKStatisticsCollectionQueryDescriptor seems to do the same, but with very different code setup.
Could anyone provide any advice on which method is preferable?
Will the older HKStatisticsCollectionQuery become obsolete in the near future?
Thanks
Tommy