From 80567d461153e66686b84214e70696d24a51d067 Mon Sep 17 00:00:00 2001 From: Sylvain Bettinelli Date: Mon, 18 May 2026 09:51:31 +0000 Subject: [PATCH] =?UTF-8?q?fix(workoutkit):=20warmup/cooldown=20nil=20quan?= =?UTF-8?q?d=20dur=C3=A9e=200=20(=C3=A9vite=20assertion=20crash)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit La signature CustomWorkout(warmup: WorkoutStep?, cooldown: WorkoutStep?) accepte nil. Or notre code passait toujours un WorkoutStep(goal: .time( warmupMin * 60, .seconds)) — avec warmupMin = 0 on créait un step de durée zéro qui déclenchait un assertion failure interne dans CustomWorkout.init (precondition Apple non catchable depuis try/catch Swift, crash dur). Confirmé via crash report iOS sur build 1.2 (14) : Thread 5 crashed → _assertionFailure → CustomWorkout.init(activity:location:displayName:warmup:blocks: cooldown:) EXC_BREAKPOINT (SIGTRAP) Fix : let warmupStep: WorkoutStep? = warmupMin > 0 ? WorkoutStep(...) : nil — idem cooldown. Permet aux apps web de pousser des séances 100% décrites en blockSteps (renforcement avec items warmup + main + aux + cooldown détaillés et nommés via displayName). Bump version requis côté Mac avant rebuild TestFlight. --- ios/App/App/CoachWorkoutKit.swift | 18 ++++++++++++++---- 1 file changed, 14 insertions(+), 4 deletions(-) diff --git a/ios/App/App/CoachWorkoutKit.swift b/ios/App/App/CoachWorkoutKit.swift index 7f1a1a5..ef2ada8 100644 --- a/ios/App/App/CoachWorkoutKit.swift +++ b/ios/App/App/CoachWorkoutKit.swift @@ -151,8 +151,15 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin { cooldownMin: Double ) async throws { - // 1. Warmup — un WorkoutStep avec un goal time - let warmupStep = WorkoutStep(goal: .time(warmupMin * 60, .seconds)) + // 1. Warmup — un WorkoutStep optionnel. Si warmupMin == 0, on passe + // nil au CustomWorkout (la signature accepte WorkoutStep?). Passer + // un WorkoutStep(goal: .time(0, .seconds)) déclenche un assertion + // failure dans CustomWorkout.init (precondition Apple non + // catchable). Cas d'usage : séances 100% décrites en blockSteps + // (renforcement avec items détaillés warmup+main+aux+cooldown). + let warmupStep: WorkoutStep? = warmupMin > 0 + ? WorkoutStep(goal: .time(warmupMin * 60, .seconds)) + : nil // 2. Construit la liste d'IntervalSteps depuis stepsSpec. // Chaque entrée = (durée min, zone HR optionnelle, isWork bool, label optionnel). @@ -177,8 +184,11 @@ public class CoachWorkoutKitPlugin: CAPPlugin, CAPBridgedPlugin { // se répète repeats fois. let block = IntervalBlock(steps: intervalSteps, iterations: repeats) - // 4. Cooldown - let cooldownStep = WorkoutStep(goal: .time(cooldownMin * 60, .seconds)) + // 4. Cooldown — idem warmup : nil si cooldownMin == 0 pour éviter + // l'assertion failure sur WorkoutStep de durée 0. + let cooldownStep: WorkoutStep? = cooldownMin > 0 + ? WorkoutStep(goal: .time(cooldownMin * 60, .seconds)) + : nil // 6. CustomWorkout — location selon l'activité (indoor pour // strength/yoga/core, outdoor pour cardio extérieur).