WorkoutKit

RSS for tag

The WorkoutKit framework provides the ability to create, preview, and schedule planned workouts for the Workout app on Apple Watch.

WorkoutKit Documentation

Posts under WorkoutKit tag

30 Posts
Sort by:
Post not yet marked as solved
4 Replies
739 Views
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.
Posted
by
Post not yet marked as solved
1 Replies
504 Views
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?
Posted
by
Post not yet marked as solved
5 Replies
1.7k Views
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?
Posted
by
Post not yet marked as solved
1 Replies
445 Views
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?
Posted
by
Post not yet marked as solved
0 Replies
445 Views
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π
Posted
by
Post marked as solved
3 Replies
461 Views
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/
Posted
by
Post not yet marked as solved
2 Replies
466 Views
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π
Posted
by
Post marked as solved
1 Replies
480 Views
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
Posted
by
Post not yet marked as solved
0 Replies
364 Views
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!
Posted
by
Post not yet marked as solved
2 Replies
502 Views
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?
Posted
by
Post not yet marked as solved
2 Replies
801 Views
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
Posted
by
Post not yet marked as solved
0 Replies
402 Views
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
Posted
by
Post not yet marked as solved
1 Replies
406 Views
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
Posted
by
Post marked as Apple Recommended
664 Views
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?
Posted
by
Post not yet marked as solved
0 Replies
503 Views
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
Posted
by
Post not yet marked as solved
2 Replies
444 Views
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.
Posted
by
Post not yet marked as solved
0 Replies
316 Views
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
Posted
by
Post not yet marked as solved
0 Replies
394 Views
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))") } } }
Posted
by