diff --git a/README.md b/README.md index 44d7a8b..4931f5f 100644 --- a/README.md +++ b/README.md @@ -50,6 +50,7 @@ If the original workout was created by our app, it is automatically deleted afte - **Activity icons in Apple Fitness are source-dependent.** Even though we correctly set `locationType` (e.g., `.indoor`) and carry over `HKMetadataKeyIndoorWorkout`, Apple Fitness may display a generic icon for workouts from third-party sources instead of the specialized icon (e.g., indoor run icon) shown for Apple Watch workouts. - **Apple Fitness may crash when sharing copied workouts.** This is a known Apple bug where Fitness crashes when trying to view interval details or share workouts created by third-party apps via `HKWorkoutBuilder`. This is not specific to Overrun. - **No deep link to specific workouts.** Apple provides no URL scheme to open a specific workout in Fitness or Health. `activitytoday://` opens Fitness to the activity rings view only. +- **Splits are not shown for third-party workouts.** Since iOS 14, Apple Fitness only displays per-kilometer/mile splits for workouts created by Apple's native Workout app. The underlying distance samples exist in HealthKit, but Fitness will not render the splits table for workouts from any third-party source. There is no API or workaround. - **Running dynamics may not be present.** Running speed, power, stride length, vertical oscillation, and ground contact time are only recorded by Apple Watch Series 6+ / Ultra with watchOS 9+. Older devices or non-running workouts will not have these samples. ### Strava diff --git a/WorkoutEditor/HealthKitManager.swift b/WorkoutEditor/HealthKitManager.swift index 29c7d3c..092e554 100644 --- a/WorkoutEditor/HealthKitManager.swift +++ b/WorkoutEditor/HealthKitManager.swift @@ -327,6 +327,25 @@ class HealthKitManager { try await builder.beginCollection(at: start) + // Add workout activities first so builder can associate samples with them + for activity in original.workoutActivities { + let activityStart = max(activity.startDate, start) + let activityEnd = min(activity.endDate ?? end, end) + guard activityStart < activityEnd else { continue } + do { + let newActivity = HKWorkoutActivity( + workoutConfiguration: activity.workoutConfiguration, + start: activityStart, + end: activityEnd, + metadata: activity.metadata + ) + try await builder.addWorkoutActivity(newActivity) + print("[Trim] Added workout activity: \(activity.workoutConfiguration.activityType.rawValue)") + } catch { + print("[Trim] Could not copy workout activity: \(error.localizedDescription)") + } + } + // Recreate samples with new objects if !samples.isEmpty { let newSamples: [HKQuantitySample] = samples.map { s in @@ -346,27 +365,6 @@ class HealthKitManager { try await builder.addWorkoutEvents(filteredEvents) } - // Copy workout activities (needed for splits display in Apple Fitness) - for activity in original.workoutActivities { - let activityStart = max(activity.startDate, start) - let activityEnd: Date - if let end = activity.endDate { - activityEnd = min(end, end) - } else { - activityEnd = end - } - if activityStart < activityEnd { - let newActivity = HKWorkoutActivity( - workoutConfiguration: activity.workoutConfiguration, - start: activityStart, - end: activityEnd, - metadata: activity.metadata - ) - try await builder.addWorkoutActivity(newActivity) - print("[Trim] Added workout activity: \(activity.workoutConfiguration.activityType.rawValue)") - } - } - if let metadata, !metadata.isEmpty { try await builder.addMetadata(metadata) }