Im building a workout app to track swimming workouts for watchos 11. Triggering .prepare() on my HKWorkoutSession does not change the session state HKWorkoutSessionState.
Below is my prepare function which should transition the session state to HKWorkoutSessionStatePrepared. Nothing is thrown in the delegates, the state just wont change? I have tried erasing, restarting, use another version of xcode and another simulator runtime.
func prepare() {
guard self.session == nil else {
fatalError("Session already exist")
}
// Configure Workout Type
let config = HKWorkoutConfiguration()
config.activityType = .swimming
config.swimmingLocationType = .openWater
config.locationType = .outdoor
self.Workoutconfig = config
// Create Session
do {
guard store.authorizationStatus(for: .workoutType()) == .sharingAuthorized else {
fatalError("Lack of permission to start workout")
}
let session = try HKWorkoutSession(healthStore: store, configuration: config)
self.session = session
self.builder = session.associatedWorkoutBuilder()
Logger.diveController.info("Successfully created workout session")
builder?.dataSource = HKLiveWorkoutDataSource(healthStore: store, workoutConfiguration: config)
self.session?.delegate = self
self.builder?.delegate = self
if self.session == nil {
fatalError("No workout session created")
}
if self.builder == nil {
fatalError("No workout builder created")
}
self.session?.prepare()
logger.debug("Session Started at: \(self.session?.startDate ?? Date())")
logger.debug("Session State: \(self.session?.state.description ?? "")")
if self.session?.state != .prepared {
reset()
fatalError("Failed To Prepare")
}
} catch {
Logger.diveController.error("Error starting workout session: \(error.localizedDescription)")
}
}
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.
Selecting any option will automatically load the page
Post
Replies
Boosts
Views
Activity
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!?!?!? 😁🤣
I´m working within the health felid with a few apps. Accordingly to science one of the most important parts to keep healthy is every day walking.
But it is not to walk slow. You need to come to a little speed (not running or even jogging). But to rais your puls. This is when you get the "real health effect". In general it is around 6km/h.
It would be great if apple could make this info available for us developers. I think lots of developers will be happa and use this to make better apps and get more people in a healtheyer life.
Looking forward to get some feedback on this.
Thank you!
Cheers
Peter
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
App Tracking Transparency
Developer Tools
SensorKit
HealthKit
As the title says, I logged in to iCloud on my simulator on my mac mini m2 and turned on icloud sync. My health data is in iCloud but it wont load in. When I go to documents for example I can see documents that I have loaded so I know something is working right.
I have tried clicking Feature -> Trigger iCloud sync with no luck.
I have tried logging out and logging back in, no luck.
I have tried Restarting the simulator with no luck.
The app I am building uses health data and there is no other way to get health data (heart rate, workouts, sleep) in the simulator. Please help, Thank you
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Xcode
HealthKit
Simulator
iCloud Drive
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
When we upload workout data to HealthKit the route information with the workout detailed data is incomplete: just a few dots.
When we select "Show all workout routes" the route data for the same workout shows correctly.
We use the HKWorkoutBuilder to store the workout data, and add the location data with the HKWorkoutRouteBuilder to the workout with
Is this an Apple Health issue, or do we have to change something in the way we store the location data to the workout?
Topic:
App & System Services
SubTopic:
Health & Fitness
In my app the the statisticsUpdateHandler fetches data from the HealthKit when I open the app from sleeping/standby state. This works fine, except when I leave the app running in the foreground and close the phone for an extended period. This triggers the .errorDatabaseInaccessible error. This seems to stop the statisticsUpdateHandler, maybe set it to nil or something similar. What is the proper way to handle the error to keep it running? As shown in the code below I have tried setting the completion data to the current data. But it stills seems to exit, and thus require a complete restart of the app to re-register the update handler.
Thanks
Tommy
Task {
do {
try await healthStore.requestAuthorization(toShare: [], read:healtTypes)
fetchPast14daysData()
} catch {
print("Error requesting access to health data")
}
}
func fetchDiscreteData(startDate: Date, type: HKQuantityTypeIdentifier, completion: @escaping([WorkoutMetric]) -> Void)
{
let datatype = HKQuantityType(type)
let interval = DateComponents(day: 1)
let query = HKStatisticsCollectionQuery(quantityType: datatype, quantitySamplePredicate: nil, options: .discreteAverage, anchorDate: startDate, intervalComponents: interval)
query.initialResultsHandler = { query, result, error in
...
}
query.statisticsUpdateHandler = { query, statistics, result, error in
var lock_error_detected: Bool = false
// Handle errors here.
if let error = error as? HKError {
switch (error.code) {
case .errorDatabaseInaccessible:
lock_error_detected = true
default:
// Handle other HealthKit errors here.
DispatchQueue.main.async {
self.update_error = error.userInfo[NSLocalizedDescriptionKey] as? String
}
return
}
}
var data = [WorkoutMetric]()
if lock_error_detected {
if (type == .heartRateVariabilitySDNN) {
data = self.HRV
} else {
data = self.restingPulse
}
} else {
guard let result = result else {
completion([])
return
}
result.enumerateStatistics(from: startDate, to: Date()) { statistics, stop in
if ( type == .heartRateVariabilitySDNN)
{
let value = Float(statistics.averageQuantity()?.doubleValue(for: .secondUnit(with: .milli)) ?? 0.0)
//print("HRV data \(value)")
if (value > 1)
{
data.append(WorkoutMetric(date: statistics.startDate, Value: value, Average: 0.0))
}
}
else if ( type == .restingHeartRate)
{
let value = Float(statistics.averageQuantity()?.doubleValue(for: .hertzUnit(with: .none)) ?? 0.0)
//print("Resting hearth rate : \(value) at date \(statistics.startDate)")
if (value > 0.01)
{
data.append(WorkoutMetric(date: statistics.startDate, Value: value*60, Average: 0.0))
}
}
}
let _ = calculate_average(days: self.averagePeriod, workouts: &data)
}
completion(data)
}
healthStore.execute(query)
}
extension HealthManager {
func fetchPast14daysData() {
fetchCumulativeData(startDate: Date().daysAgoAligned(days: daysToFetchDataFor), type: .distanceWalkingRunning) { dailyDistance in
DispatchQueue.main.async {
self.distanceData = dailyDistance
}
..
..
Topic:
App & System Services
SubTopic:
Health & Fitness
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
Topic:
App & System Services
SubTopic:
Health & Fitness
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 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.
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Family Controls
Device Activity
Screen Time
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?
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?
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Health and Fitness
watchOS
Apple Watch
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
Topic:
App & System Services
SubTopic:
Health & Fitness
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
Topic:
App & System Services
SubTopic:
Health & Fitness
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?
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
iOS
iPhone
Health and Fitness
HealthKit
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.
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
Topic:
App & System Services
SubTopic:
Health & Fitness
Tags:
Health and Fitness
HealthKit
TestFlight
In my WatchOS app I've written the following code to check if my app has access to the user's health data:
func isHealthKitAuthorized() -> Bool {
let typesToRead: [HKObjectType] = [
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: .appleMoveTime)!,
HKObjectType.quantityType(forIdentifier: .appleExerciseTime)!,
HKObjectType.workoutType()
]
let typesToShare: Set<HKSampleType> = [
HKObjectType.workoutType(),
HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!,
HKObjectType.quantityType(forIdentifier: .heartRate)!
]
var isAuthorized = true
for type in typesToRead {
let status = healthStore.authorizationStatus(for: type)
if status != .sharingAuthorized {
print("Access denied to: \(type.identifier)")
isAuthorized = false
}
}
for type in typesToShare {
let status = healthStore.authorizationStatus(for: type)
if status != .sharingAuthorized {
print("Access denied to: \(type.identifier)")
isAuthorized = false
}
}
return isAuthorized
}
However for the appleMoveTime and appleExerciseTime types their status is returning as 'sharingDenied' (checked by printing the status' rawValue) even though they are authorized on the Watch's settings. This happened both on the simulator and on the Watch itself. Am I doing something wrong?
Hello,
I am currently working on an app that uses HealthKit to sync health data to a backend server that performs analysis on this data. I am keeping track of the synced data with the HKQueryAnchor I receive for each query I make.
I want to address an edge case: if a user has multiple devices running the app, would it make sense to store the anchor on my backend? This would ensure that other instances of the app do not sync data that has already been synced from another device.
Thank you for your help!
I am using a new Apple Watch Ultra 2 (MX5R3LW/A) running WatchOS 11.3 (22S553).
I noticed that the watch often misses heart measurements during meaningfully long segments of exercise sessions. This has been bugging me for a while and today I read an article that described perfectly, and much better than I could, what I am experiencing. Here is the article: https://apple.news/AK_QJyoLaQ1eaeySWHlkLPw
Is this a known issue that is being worked?
Thanks.
Topic:
App & System Services
SubTopic:
Health & Fitness