Post not yet marked as solved
hello
We are currently developing using Healthkit.
Starting with xcode15, healthkit throws an error.
The code causing the error is HKQuantityType(.stepCount).
When I use this code
An EXC_BAD_ACCESS (code=1, address=0x0) error occurs.
The error is:
AppDelegate
It also appears when I call didFinishLaunchingWithOptions.
Is the linker the problem?
Or is the Swift version the problem?
Or HealthKit?
Cleaning and initializing DerivedData
I also tried downgrading DriverKit 22.4, but the error still appears.
Please tell me how to solve this problem.
Test model information is as follows:
-iPhone 14 Pro
iOS 16.5.1
Post not yet marked as solved
hello
After updating to xcode 15.1 while using xcode 14.3, I keep getting EXC_BAD_ACCESS (code=1, address=0x0) in HealthKit's HKQuantityType(.stepCount).
We also created and tested HKQuantityType(.stepCount) in the appDelegate class. But it comes out the same as above.
I think there has been a change in library building and linking starting from xcode15.
Please guide me what to do about this problem.
The test model is
iphone 14 pro
It's 16.5.1.
Post not yet marked as solved
Errors:
''Invalid info.plist key. The key 'NSHealthShareUsageDescription''
''Invalid info.plist key. The key 'NSHealthUpdateUsageDescription''
The app works fine when I just run it on hardware without deployment, but as soon as I try to distribute it, this shows up.
The keys above are both defined and described in my App and extensions lists, so what's wrong?
Post not yet marked as solved
I have the same issues, when i use HKStatisticsCollectionQuery query user step count, there's a big difference in the number of steps I'm query before and after a minute's interval.
2023-12-17 15:45:41 steps=529
2023-12-17 15:46:52 steps=5817
2023-12-19 19:43:59 steps=2680
2023-12-19 19:44:31 steps=5554
What is causing this issue? I would like some assistance, please.
Post not yet marked as solved
With the recent iPad OS 17 release, Apple added the Health app for the first time. Looking at it, it seems pretty similar to the phone version as the Health app only shows 'historical' health data.
My question is this: We are developing an iPad based fitness app. Is there any way of getting real-time health data from the Apple Watch directly to an iPad app? (basically, we just need heart rate). Or, do we have create some sort of workflow through the Phone like
Watch -> iPhone running our app -> our servers -> iPad running our app
..to get that real-time data?
We really just want Watch -> iPad running our app.
I'm afraid I already know the answer but just thought I'd check in case I'm missing something in iOS 17.
Thanks!
Post not yet marked as solved
Our app uses HKWorkoutSession after some actions, to keep app on high priority in background and to keep Apple Watch returns to our app when the watch is waked up. We don't collect or register any activity record.
But for some reasons, some users reviewed our app saying that when they're using our app, the Workout app on Apple Watch seems to be affected, ex: Move and exercises is recorded as an abnormal/impossible value... .
Is this possible? I don't see any document mention this side effect?
Post not yet marked as solved
Hello, it is discussed here https://developer.apple.com/videos/play/wwdc2023/10016/ (12:16) regarding WorkoutComposition, but unfortunately, I cannot find this class or structure in the documentation. Has this concept been removed?
Post not yet marked as solved
I have created a new project and I have added HomeKit capability but the two control box for Clinical Health Records
and Background Delivery can not be switched on.
are there any suggestion?
thanks a lot
valerio
Post not yet marked as solved
After some years our app has been writing some data to HealthKit we decided to remove this functionality from the app. Permissions were removed from requestAuthorization(toShare:read:completion:) method. For new users everything works fine, but for users who were already asked for writing permission in Settings toggles for permissions are still on. Is it any way to update toggles list in Settings for actual state of permissions? Thanks in advance.
Post not yet marked as solved
Hi,
Our app has an HKObserverQuery and calls enableBackgroundDelivery(...)
While running on an iPhone the background wakeup happens. While running on an iPad, it doesn't. The app can successfully query for data while in the foreground on an iPad.
Is background delivery expected to work on iPad?
Post not yet marked as solved
Even if you have granted read permission for specific health data items (such as walking, weight, etc.), calling the function below will return the permission as 'sharingDenied'. How can I obtain 'sharingAuthorized'?
let stepType = HKObjectType.quantityType(forIdentifier: .stepCount)!
let authorizationStatus = HKHealthStore().authorizationStatus(for: stepType)
//authorizationStatus => sharingDenied
Post not yet marked as solved
https://idmsa.apple.com/IDMSWebAuth/signin?path=%2F%2Fforums%2Fpost%2Fquestion%3Flogin%3Dtrue&language=US-EN&instanceId=EN&appIdKey=25138a77e3499638936f018102a53961c923f72b517d4a4d6aee9f09529baca9&rv=4
I've built and tested the code obtained from this site, but although the session starts, pausing or stopping it doesn't seem to work properly. Does anyone know what might be causing this issue?
I'm using the latest versions of iOS and watchOS, and my Xcode is version 15.0.1.
The main code is as follows, and the session does not start properly in startWorkout.
import Foundation
import os
import HealthKit
@MainActor
class WorkoutManager: NSObject, ObservableObject {
struct SessionSateChange {
let newState: HKWorkoutSessionState
let date: Date
}
@Published var sessionState: HKWorkoutSessionState = .notStarted
@Published var heartRate: Double = 0
@Published var activeEnergy: Double = 0
@Published var speed: Double = 0
@Published var power: Double = 0
@Published var cadence: Double = 0
@Published var distance: Double = 0
@Published var water: Double = 0
@Published var elapsedTimeInterval: TimeInterval = 0
@Published var workout: HKWorkout?
let typesToShare: Set = [HKQuantityType.workoutType(),
HKQuantityType(.dietaryWater)]
let typesToRead: Set = [
HKQuantityType(.heartRate),
HKQuantityType(.activeEnergyBurned),
HKQuantityType(.distanceWalkingRunning),
HKQuantityType(.cyclingSpeed),
HKQuantityType(.cyclingPower),
HKQuantityType(.cyclingCadence),
HKQuantityType(.distanceCycling),
HKQuantityType(.dietaryWater),
HKQuantityType.workoutType(),
HKObjectType.activitySummaryType()
]
let healthStore = HKHealthStore()
var session: HKWorkoutSession?
#if os(watchOS)
var builder: HKLiveWorkoutBuilder?
#else
var contextDate: Date?
#endif
let asynStreamTuple = AsyncStream.makeStream(of: SessionSateChange.self, bufferingPolicy: .bufferingNewest(1))
static let shared = WorkoutManager()
private override init() {
super.init()
Task {
for await value in asynStreamTuple.stream {
await consumeSessionStateChange(value)
}
}
}
/**
Consume the session state change from the async stream to update sessionState and finish the workout.
*/
private func consumeSessionStateChange(_ change: SessionSateChange) async {
sessionState = change.newState
/**
Wait for the session to transition states before ending the builder.
*/
#if os(watchOS)
/**
Send the elapsed time to the iOS side.
*/
let elapsedTimeInterval = session?.associatedWorkoutBuilder().elapsedTime(at: change.date) ?? 0
let elapsedTime = WorkoutElapsedTime(timeInterval: elapsedTimeInterval, date: change.date)
if let elapsedTimeData = try? JSONEncoder().encode(elapsedTime) {
await sendData(elapsedTimeData)
}
guard change.newState == .stopped, let builder else {
return
}
let finishedWorkout: HKWorkout?
do {
try await builder.endCollection(at: change.date)
finishedWorkout = try await builder.finishWorkout()
session?.end()
} catch {
Logger.shared.log("Failed to end workout: \(error))")
return
}
workout = finishedWorkout
#endif
}
}
// MARK: - Workout session management
//
extension WorkoutManager {
func resetWorkout() {
#if os(watchOS)
builder = nil
#endif
workout = nil
session = nil
activeEnergy = 0
heartRate = 0
distance = 0
water = 0
power = 0
cadence = 0
speed = 0
sessionState = .notStarted
}
func sendData(_ data: Data) async {
do {
try await session?.sendToRemoteWorkoutSession(data: data)
} catch {
Logger.shared.log("Failed to send data: \(error)")
}
}
}
extension WorkoutManager: HKWorkoutSessionDelegate {
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
didChangeTo toState: HKWorkoutSessionState,
from fromState: HKWorkoutSessionState,
date: Date) {
Logger.shared.log("Session state changed from \(fromState.rawValue) to \(toState.rawValue)")
let sessionSateChange = SessionSateChange(newState: toState, date: date)
asynStreamTuple.continuation.yield(sessionSateChange)
}
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
didFailWithError error: Error) {
Logger.shared.log("\(#function): \(error)")
}
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
didDisconnectFromRemoteDeviceWithError error: Error?) {
Logger.shared.log("\(#function): \(error)")
}
nonisolated func workoutSession(_ workoutSession: HKWorkoutSession,
didReceiveDataFromRemoteWorkoutSession data: [Data]) {
Logger.shared.log("\(#function): \(data.debugDescription)")
Task { @MainActor in
do {
for anElement in data {
try handleReceivedData(anElement)
}
} catch {
Logger.shared.log("Failed to handle received data: \(error))")
}
}
}
}
private func startWorkout() {
Task {
do {
let configuration = HKWorkoutConfiguration()
configuration.activityType = .cycling
configuration.locationType = .outdoor
try await workoutManager.startWorkout(workoutConfiguration: configuration)
} catch {
Logger.shared.log("Failed to start workout \(error))")
}
}
}
Post not yet marked as solved
With iOS 17 creation of HKWorkout is deprecated via its init functions and the recommendation is to use HKWorkoutBuilder. If you try to init HKWorkout like you would pre iOS 17 you get this warning of deprecation:
The problem is that I am creating this HKWorkout object inside unit tests in order to test a service that works with such objects. And HKWorkoutBuilder requires a HKHealthStore which itself requires to be authenticated to be able to create HKWorkoutActivity instances, like it would be when an app is running. But since the unit tests cannot accept the request on the HKHealthStore I am not sure if using HKWorkoutBuilder inside unit tests is possible.
I've also tried to inherit HKHealthStore and override all of its methods, but still, store requires authorization.
Any ideas on how to proceed with creating HKWorkout for unit test purposes?
Post not yet marked as solved
Hello developers,
I hope you're all doing well. I've encountered an issue that I'm struggling to resolve, and I'd greatly appreciate any insights or assistance you can offer.
Issue Summary:
In my watchOS app, I'm utilizing the HKWorkoutSessionDelegate protocol and the workoutSession(_:didFailWithError:) method. While everything works smoothly on watchOS 9.*, I'm facing a problematic inconsistency on watchOS 10.0 and higher.
Steps to Reproduce:
Create a new watchOS project with a deployment target of watchOS 10.0 or higher.
Implement the HKWorkoutSessionDelegate protocol and the workoutSession(_:didFailWithError:) method.
Attempt to start a workout session.
Expected Behavior:
I expect the workout session to commence without any issues, and the delegate method to gracefully handle any errors, without displaying an error message.
Actual Behavior:
Unfortunately, on watchOS 10.0 and higher, my attempts to initiate a workout session result in an error message: "Cannot start workout session while process is in the background."
Version/Build:
Affected watchOS versions: 10.0 and higher
Non-affected watchOS versions: 9.*
Reproducibility:
I've confirmed that this issue is reproducible across different projects and on different simulators running watchOS 10.0 and higher.
Additional Information:
This inconsistency seems to be specific to watchOS versions 10.0 and higher and doesn't occur on watchOS 9.*. It's causing confusion and hampering my development process, and the error message isn't as informative as I'd like.
Workaround:
I've been unable to identify a workaround for this issue so far. If any of you have insights, solutions, or suggestions, I'd be grateful for your input.
Please feel free to share your experiences and thoughts on this matter. Your help is greatly appreciated!
Thank you for your time and assistance.
Best regards,
Leonid
iPadOS 17 brings HealthKit to the iPad. So I've updated my HealthKit-using app to also run on iPadOS. I can debug it from Xcode on iPad simulators and my iPad, but when I upload a build to AppStoreConnect from Xcode and try to install it on my iPad from TestFlight, the install-button is missing and instead there is a label saying "incompatible hardware".
The app has no other required device capabilities besides healthkit. It was also updated to at least require iOS/iPadOS 17. I can install it on my iPhone but not on the iPad.
I also noticed that in this list https://developer.apple.com/support/required-device-capabilities/#ipad-devices no iPad model has the healthkit device capability. Why?
Is there some way to find out why exactly TestFlight thinks the iPad is incompatible hardware?
Thanks in advance to anyone who can enlighten me here.
Post not yet marked as solved
In the wwdc2023-10023 session, we go over how the Apple Watch can be used as a primary workout session manager and the iPhone as the mirrored one. How is it possible to create a workout session on the iPhone and optionally mirror it to the Apple Watch to collect heart rate data?
In iOS 17, I still cannot instantiate a HKWorkoutSession, I'm assuming it says it's available because we can have an instance of it as a mirrored copy from the Apple Watch. I find it odd that the iPhone cannot manage the primary session. I hope I'm missing something.
Post not yet marked as solved
Hi, with iOS 17 creation of HKWorkout is deprecated via its init functions and the recommendation is to use HKWorkoutBuilder:
The problem is that I am creating this HKWorkout object inside unit tests in order to test a service that works with such objects. And HKWorkoutBuilder requires a HKHealthStore which itself requires to be authenticated to be able to create HKWorkoutActivity instances, like it would be when an app is running. But since the unit tests cannot accept the request on the HKHealthStore I am not sure if using HKWorkoutBuilder inside unit tests is possible.
Any ideas on how to proceed with creating HKWorkout for unit test purposes?
Post not yet marked as solved
The app I distribute has a function that retrieves step count information from the "Healthcare" app and displays it on the app, but depending on the device, the step count may not be retrieved.
When I checked the settings of the "Healthcare" app, I found that it was properly linked to the app, but for some reason I was unable to retrieve it. Is there any countermeasure in such a case?
Is there anyone who has experienced a similar incident?*The same issue occurs even if the device is changed and the same Apple ID is used, so I think it is caused by the Apple ID.
Post not yet marked as solved
Hi, I am having some trouble with uploading HealthKit data to AWS S3 in the background. As of now, when I click on the button to beginBackgroundUpdates the data is uploaded as expected. When I go off the app and add data to HealthKit nothing happens. When I go back to the app, the new data is uploaded. I am not sure why this is not happening in the background. More specifically, I am not sure if this is allowed, and if so what I am doing wrong.
ContentView:
import SwiftUI
import HealthKit
struct ContentView: View {
@StateObject var healthKitManager = HealthKitManager()
var body: some View {
VStack {
Button("Enable Background Step Delivery") {
healthKitManager.beginBackgroundUpdates()
}
}
.padding()
.onAppear {
healthKitManager.requestAuthorization { success in
print("Configured HealthKit with Return: \(success)")
}
}
}
}
#Preview {
ContentView()
}
BackgroundDeliveryApp:
import SwiftUI
import HealthKit
import Amplify
import AWSS3StoragePlugin
import AWSCognitoAuthPlugin
@main
struct HKBackgruondDeliveryApp: App {
private func configureAmplify() {
do {
try Amplify.add(plugin: AWSCognitoAuthPlugin())
try Amplify.add(plugin: AWSS3StoragePlugin())
try Amplify.configure()
print("Succesfully configured Amplify with S3 Storage")
} catch {
print("Could not configure Amplify")
}
}
init() {
configureAmplify()
}
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
HealthKitManager
import Foundation
import HealthKit
import Amplify
struct TestStep: Encodable, Decodable {
let count: Double
let startDate: Date
let endDate: Date
let device: String
}
class HealthKitManager: ObservableObject {
var healthStore: HKHealthStore?
let stepType = HKObjectType.quantityType(forIdentifier: .stepCount)
let heartRateType = HKQuantityType(.heartRate)
let sleepType = HKObjectType.categoryType(forIdentifier: .sleepAnalysis)
init() {
if HKHealthStore.isHealthDataAvailable() {
healthStore = HKHealthStore()
} else {
print("There is no health data available")
healthStore = nil
}
}
func encodeStepList(stepList: [TestStep]) -> Data{
let encoder = JSONEncoder()
encoder.dateEncodingStrategy = .iso8601
do {
return try encoder.encode(stepList)
} catch {
return Data()
}
}
func uploadStepData(stepList: [TestStep]) async {
let stepData = self.encodeStepList(stepList: stepList)
let uploadTask = Amplify.Storage.uploadData(
key: "ExampleKey",
data: stepData
)
Task {
for await progress in await uploadTask.progress {
print("Progress: \(progress)")
}
}
do {
let value = try await uploadTask.value
print("Completed: \(value)")
} catch {
print("Could not upload step data")
}
}
func requestAuthorization(completion: @escaping (Bool) -> Void) {
guard let stepType = stepType, let sleepType = sleepType else {
return completion(false)
}
guard let healthStore = self.healthStore else {
return completion(false)
}
healthStore.requestAuthorization(toShare: [], read: [stepType, heartRateType, sleepType]) { success, error in
if let error = error {
print("Some error has occoured during authorization of healthKit")
print(error)
}
return completion(success)
}
}
func beginBackgroundUpdates() {
guard let healthStore = healthStore, let stepType = stepType else {
print("Cannot begin background updates because HealthStore is nil")
return
}
healthStore.enableBackgroundDelivery(for: stepType, frequency: .immediate) { success, error in
print("Background update of health data")
if let error = error {
print("Some error has occoured during the set up of the background observer query for steps")
print(error)
return
}
guard let query = self.createObserverQuery() else {
print("Could not create a query for steps")
return
}
healthStore.execute(query)
}
}
func stepCountDeviceRecordsQuery(stepCountObjects: @escaping ([TestStep]) -> Void) {
guard let stepType = stepType else {
print("Nil step type")
return
}
let stepCountUnit = HKUnit.count()
let endDate = Date()
let startDate = Calendar.current.date(byAdding: .day, value: -7, to: endDate)
let predicate = HKQuery.predicateForSamples(withStart: startDate, end: endDate)
let sortDescriptors = [NSSortDescriptor(key: HKSampleSortIdentifierStartDate, ascending: true)]
let stepCountQuery = HKSampleQuery(sampleType: stepType, predicate: predicate, limit: 10000, sortDescriptors: sortDescriptors) { query, results, error in
if let error = error {
print("Error in getStepCount")
print(error)
return
}
guard let results = results else {
print("Empty results in getStepCount")
return
}
var stepCounts: [TestStep] = []
for (_, record) in results.enumerated() {
guard let record: HKQuantitySample = record as? HKQuantitySample else {return}
let step = TestStep(count: record.quantity.doubleValue(for: stepCountUnit), startDate: record.startDate, endDate: record.endDate, device: record.device?.model ?? "")
stepCounts.append(step)
}
print("\(stepCounts.count) records at \(Date())")
print(stepCounts[stepCounts.count - 1])
stepCountObjects(stepCounts)
}
healthStore?.execute(stepCountQuery)
}
private func createObserverQuery() -> HKQuery? {
guard let stepType = stepType else {
return nil
}
let query = HKObserverQuery(sampleType: stepType, predicate: nil) { query, completionHandler, error in
self.stepCountDeviceRecordsQuery { stepList in
Task {
await self.uploadStepData(stepList: stepList)
}
}
completionHandler()
}
return query
}
}
Post not yet marked as solved
Hi guys,
I'm delveloping an app that use HealthData. I use this data:
HKWorkoutType.workoutType(),
HKObjectType.quantityType(forIdentifier: .heartRate)!,
HKObjectType.quantityType(forIdentifier: .distanceSwimming)!
I would like use Simulator to test app, but there aren't data.
How can I import data?
Now to test my app use only my iPhone, but in this way I don't test multiple device to test my app.
Could you help me?
Thank you.
Filippo