Post not yet marked as solved
I am unable to see the workout composition from preview in the new WorkoutKit framework.
This is reproducible on an iPhone running iOS 17.0 running xcode 15.0 beta 2.
I downloaded the Sample Planner app that showcases the new WorkoutKit framework capabilities , introduced in the session 10016 of wwdc 23.
I can create workout compositions but the preview presentation doesn’t work as expected. It shows a black screen without any info. I attached a screenshot.
You can reproduce it on the sample app when showing the PresentPreviewDemo view.
Post not yet marked as solved
Hello, I'm trying to understand what's the difference between:
HeartRateZoneAlert: static func heartRate(zone: Int) -> Self
PowerZoneAlert : static func power(zone: Int) -> Self
And also, why HeartRate alerts support range, but Power doesn't support Range?
Post not yet marked as solved
Hello folks,
I have been observing a strange behaviour on my Apple Watch Ultra.
Device Environment:
Apple Watch Ultra on WatchOS 10 Beta
Offline
Disconnected from companion iPhone
Workout active: "Walking"
Expected behaviour:
The workout should record accurate locations (with accuracy of approximately 3-4 meters). This level of accuracy is already being achieved in the same watch (verified using several GPS status apps) when a workout is not active.
.
Observed behaviour:
Accuracy as good as 2 meter is observed when no workouts are active, but as soon as the workout starts, the accuracy drops to a maximum of 14 meters and never gets better than this. This is confirmed to be happening every single time and is verified using several GPS status apps during the workout.
Does anyone else has faced similar behaviour?
Post not yet marked as solved
I tried the sample code from 'Customizing workouts with WorkoutKit' all works fine on the simulator, however, I have the following error when testing on device (iPhone SE):
Error Domain=WorkoutKit.StateError Code=0 "(null)"
On launch, this is associated with 'failed to retrieve scheduled plans'. Also the same when requesting authorization.
Any ideas on this one?
Post not yet marked as solved
I was wondering which of the hkquantitytypeidentifiers I can collect while a workout is running.
Essentially which of these types are actually being collected by the sensors on the apple watch rather than being read from manual input.
Thanks
Post not yet marked as solved
Hi!
I'm working on WorkoutKit application and, when I'm running my UI Tests, I added an InterruptionMonitor for the WorkoutScheduler access popup, but the second time I launch the UITests, the Popup does not appear anymore cause the permission is guaranteed.
The only solution that I've dounded is to add the app.resetAuthorizationStatus into the tearDown, but the parameter I should provide to this method, is a XCUIProtectedResource which does not contain any enum case that match with what I'm looking for.
Does someone find a solution for that?
Thanks,
Victor Kπ
I'm using Xcode Version 15.0 beta (15A5160n) and getting the following error:
Value of type 'HKWorkoutSession' has no member 'sendToRemoteWorkoutSession'
Any idea what's causing this? I pulled the code from https://developer.apple.com/videos/play/wwdc2023/10023/
Post not yet marked as solved
Hi!
How can I authorize the WorkoutScheduler permissions after I denied if I can't see any option in Settings to make it? (Like Notification or Localization permission)
Thank you!
Victor Kπ
Hi,
I am running the "Building a multidevice workout app" sample:
https://developer.apple.com/documentation/healthkit/workouts_and_activity_rings/building_a_multidevice_workout_app
I do not get any values for the .cyclingSpeed Value?
Is this correct or should there be any value while moving around?
Also i wonder if i can get the GPS values like altimeter or location from the HKWorkoutSession?
Thanks
Post not yet marked as solved
Hey team! I have a question that feels very obvious, but I cannot seem to find the answer in the documentation. Using HealthKit/WorkoutKit, how you can make workouts with different activity types? Say you do 10 minutes of traditionalStrengthTraining followed by 10 minutes of running (common for crossfit and similar high intensity workout styles)? From the docs, it looks like you can’t change the activity type on an HKWorkout and the new dividing workouts into activities concept seems to only be for swimBikeRun workouts. Do you simply make multiple consecutive HKWorkoutSession instances, e.g doing startActivity -> beginCollection -> endCollection multiple times?
Any input is highly appreciated!
Post not yet marked as solved
Hi,
I have an app that implements the Cycling Power Service 1.1, https://www.bluetooth.com/de/specifications/specs/cycling-power-service-1-1/
As expected, I can select this app as a Health Device in the Bluetooth settings of my Apple Watch.
However, when I run the BLE app on the paired iPhone, the Apple Watch does not detect the BLE Service as a Health Device!
Is this a bug, or is it designed this way?
If so, is there another API where I can send power meter data from iOS to a running Watch Workout?
Post not yet marked as solved
Hi,
I'm the developer of Open Water Swim, and I have had multiple reports and have also confirmed with my own testing that the WatchOS 10 update has seriously degraded GPS data during open water swimming, both with the native Workout app and with Open Water Swim. The data provided by CoreLocation is no longer accurate or trustworthy. I will post several pictures showing before and after update swims:
Here's the raw data (mapped) of a swim done with watchOS 9 on the Ultra.
Same swim today:
From another pair of users: These two went TOGETHER, one with watchOS 9 and one with watchOS 10. You can probably guess which is which.
Watch OS 9 swim:
SAME SWIM WITH A PARTNER ON WATCHOS 10 (beta here)
And another, again, two people swimming together, one watchOS 9 and one watchOS 10.
watchOS 9
Same swim, same time, watchOS 10
I have filed two feedback assistant reports with APPLE. One when it was still a beta issue: FB12587468. This one has zero response from apple.
And now a second one filed with watchOS 10 release: FB13192409
Apple devs, I know you're here and listening, so please let's get this fixed ASAP. Thanks
Post not yet marked as solved
Hi there,
Thanks for the great tutorial for WorkoutKit, that can be found here: https://developer.apple.com/videos/play/wwdc2023/10016/
In my view
Text(scheduledWorkout.plan.workout.activity.displayName) in
SamplePlannerView.swift (the main view)
does not show the correct string. For example for the running workout, it should show: "New Running Workout". This string is set in WorkoutStore.swift. However, it shows "Outdoor Running", which is the type of workout but not the display name that was given to it.
Best regards,
Patrick
Post not yet marked as solved
Dear All,
Is there a way to remove a workout? In the tutorial app, it is shown how to schedule workouts. But so far, I haven't seen a way to remove them again, neither from the tutorial app nor from the workouts app on the watch.
Many thanks and best regards,
Patrick
Post marked as Apple Recommended
I am having trouble getting the new mirroring session API to send data to the companion device.
when starting a workout on my watch I call startMirroringToCompanionDevice and then go onto my iOS workout manager to handle it via the workoutSessionMirroringStartHandler, I set the delegate here and can confirm that it is indeed not nil within that function but when I go to send some data across I get an error saying the remote session delegate was never set up.
I noticed this same behaviour in the WWDC demo and have been unable to find a solution that will allow me to send data across the mirrored session even though I am able to control the workout session state(pause, resume, end) on both Phone and Watch.
Has anyone else encountered this issue? Anyone have a solution?
Post not yet marked as solved
I was wondering which of the hkquantitytypeidentifiers I can collect while a workout is running.
Essentially which of these types are actually being collected by the sensors on the apple watch rather than being read from manual input.
Thanks
Post not yet marked as solved
I'm experiencing an issue trying to install the 'mirroringworkoutssample' app from the official Apple documentation on my Apple Watch. When attempting a direct installation from the Apple Watch, I receive an error stating, "Cannot install this app due to an inability to verify its integrity."
Has anyone else encountered this problem or can provide any solutions or insights?
** I have a 'Development' type certificate that allows for watchOS(it includes iOS, tvOS ..) development.
** also added WKCompanionAppBundleIdentifier com.example.apple-samplecode.MirroringWorkoutsSample7C76V3X7AB.watchkitapp
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,
Is there anyway to share a WorkoutScheduler across an iPhone and watch app? If I create a scheduler on the phone app the watch app can't see it and creates its own. I'm using WorkoutScheduler.shared.scheduledWorkouts but end up with two identical sections at the top of the workout app
Thanks
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))")
}
}
}