HealthKit Workout Lifecycle: HKWorkoutSession-Zustände und die plattformübergreifende Oberfläche von iOS 26
HKWorkoutSession ist der Zustandsautomat von HealthKit für Workouts. Die Session durchläuft sechs Zustände (.notStarted, .prepared, .running, .paused, .stopped, .ended), stellt Lebenszyklus-Ereignisse über HKWorkoutSessionDelegate bereit und läuft (seit iOS 26) zusätzlich zur Apple Watch auch auf dem iPhone1. Ein HKLiveWorkoutBuilder gepaart mit der Session sammelt Samples und Ereignisse inkrementell; iOS 26 brachte denselben Builder API auf das iPhone. Der Beitrag watchOS Runtime Contract des Clusters argumentierte, dass watchOS-Apps einen anerkannten Session-Typ benötigen, um im Hintergrund weiterzulaufen; HKWorkoutSession ist einer dieser Session-Typen, und die Lebenszyklus-Zustände bilden direkt das Runtime-Modell ab.
Der Beitrag geht den Workout-Lebenszyklus anhand von Apples Dokumentation durch. Der Rahmen lautet „Was erlaubt jeder Zustand und was löst jeder Übergang aus?”, denn Workout-Apps, die den Lebenszyklus falsch verwalten, verlieren entweder Daten (zu früher Übergang aus dem Running-Zustand) oder leeren den Akku (gar kein Übergang aus dem Running-Zustand).
TL;DR
HKWorkoutSession-Lebenszyklus:notStarted→prepared→running→ (optionalpaused→running) →stopped→ended. Übergänge werden überHKWorkoutSessionDelegate.workoutSession(_:didChangeTo:from:date:)gemeldet2.HKLiveWorkoutBuilderist der Live-Datenakkumulator, der mit der Workout-Session gekoppelt ist. Er erschien 2018 auf watchOS und wurde mit iOS 26+, iPadOS 26+ und Mac Catalyst 26+ ausgeliefert. iPhone-Workouts nutzen denselbenHKLiveWorkoutBuilderAPI wie die Apple Watch, mit plattformspezifischen Unterschieden im Runtime-Modell und in der Sensorverfügbarkeit3.- Die Methode
prepare()der Session wärmt die Sensoren auf, bevorstartActivity(_:)das eigentliche Workout startet. Apples Empfehlung ist eine 3-sekündige Countdown-UI zwischenprepare()undstartActivity(_:), damit Herzfrequenzsensoren und externe Bluetooth-Geräte Zeit haben, sich zu verbinden. - Der
stopped-Zustand ist transient: Apps können in diesem Zustand Metriken finalisieren, aber die Session nicht fortsetzen. Der Aufruf vonend()führt zum Übergang inended, was terminal ist. - Der Beitrag watchOS Runtime Contract des Clusters behandelt, wie die Workout-Session die watchOS-App während des Wrist-Drop am Laufen hält. Der Lebenszyklus-Zustandsautomat und der Runtime-Keep-Alive-Vertrag sind die zwei Hälften derselben Oberfläche.
Die sechs Zustände
HKWorkoutSessionState zählt den Lebenszyklus auf2:
.notStarted. Die Session wurde erstellt, aber nicht vorbereitet. Sensoren sind nicht aufgewärmt; die App gilt noch nicht als aktiver Workout-Host. Der Übergang zu .prepared erfolgt, wenn die App prepare() aufruft.
.prepared. Die Session hat prepare() aufgerufen; Sensoren wärmen sich auf, aber das Workout hat noch nicht begonnen. Herzfrequenzmonitore verbinden sich, Bewegungssensoren initialisieren sich, GPS erhält einen Fix. Das nutzerseitige Muster ist ein 3-sekündiger Countdown („Fertig machen … 3, 2, 1, LOS!”); in diesem Zeitfenster hat das System Zeit, ein sauberes Signal zu erfassen, sodass die ersten Metriken im Running-Zustand präzise sind.
.running. Der aktive Workout-Zustand. Die App sammelt Metriken, zeigt Live-Daten an und (auf watchOS) hält den Bildschirm über den Workout-Active-Runtime-Vertrag eingeschaltet. Der Übergang in .running erfolgt über startActivity(_:).
.paused. Ein vom Benutzer pausierter Zustand. Die App sammelt keine aktiven Metriken mehr (z. B. Distanz), aber die Session bleibt erhalten; der Aufruf von resume() führt zurück zu .running. Der Pause-/Resume-Zyklus kann beliebig oft innerhalb einer einzelnen Session erfolgen.
.stopped. Ein transienter Post-Workout-Zustand. Die Session hat ihre aktive Phase beendet, ist aber noch nicht finalisiert; der Live-Builder kann weiterhin Metriken finalisieren. Aus .stopped führt der Aufruf von end() zum Übergang in .ended. Die App kann aus .stopped nicht fortsetzen.
.ended. Der Endzustand. Die Session ist abgeschlossen; dem Live-Builder wurde mitgeteilt, dass er finalisieren soll; das Workout wird in HealthKit gespeichert (sofern die App finishWorkout(completion:) auf dem Builder aufgerufen hat). Einmal in .ended, ist die Session nicht mehr manipulierbar.
Das Zustandsdiagramm hat eine konkrete Stolperfalle: Es gibt keinen Pfad von .stopped zurück zu .running. Ein Workout, das der Benutzer „rückgängig machen” möchte, muss eine neue Session starten, nicht die alte fortsetzen.
Die Methoden, die Übergänge auslösen
HKWorkoutSession stellt die folgenden Methoden für Zustandsübergänge bereit1:
prepare(). Übergang von.notStartedzu.prepared. Wärmt die Sensoren auf.startActivity(with: Date). Übergang von.preparedzu.running. DerDate-Parameter erlaubt der App, die offizielle Startzeit festzulegen (typischerweise.now).pause(). Übergang von.runningzu.paused.resume(). Übergang von.pausedzurück zu.running.stopActivity(with: Date). Übergang von.running(oder.paused) zu.stopped. DasDateist die offizielle Endzeit.end(). Übergang von.stoppedzu.ended.
Das Muster von prepare() zu startActivity(_:) ist das Aufwärm-Fenster. Das Muster von stopActivity(_:) zu end() ist das Aufräum-Fenster: Der Live-Builder erhält die Möglichkeit, finale Samples hinzuzufügen, bevor die Session terminiert.
HKLiveWorkoutBuilder auf watchOS und iPhone
HKLiveWorkoutBuilder ist der Live-Datenakkumulator, der mit der Session gekoppelt ist3. Der Builder erschien auf watchOS in watchOS 5 und wurde auf iOS 26+, iPadOS 26+ und Mac Catalyst 26+ erweitert. Der Lebenszyklus des Builders ist mit dem der Session gekoppelt:
let configuration = HKWorkoutConfiguration()
configuration.activityType = .running
configuration.locationType = .outdoor
let session = try HKWorkoutSession(healthStore: store, configuration: configuration)
let builder = session.associatedWorkoutBuilder()
builder.dataSource = HKLiveWorkoutDataSource(healthStore: store, workoutConfiguration: configuration)
session.delegate = self
builder.delegate = self
session.prepare()
// User taps Start after countdown
session.startActivity(with: Date())
try await builder.beginCollection(at: Date())
// During the workout, metrics flow into the builder via the data source.
// builder.collectedTypes contains the sample types being collected.
// builder.statistics(for:) returns running stats.
// User ends the workout
session.stopActivity(with: Date())
try await builder.endCollection(at: Date())
let workout = try await builder.finishWorkout()
session.end()
Drei Bausteine fügen das Workout zusammen:
HKWorkoutConfigurationspezifiziert Aktivitätstyp und Ort. Der Aktivitätstyp steuert die Metrikauswahl (ein Lauf-Workout erfasst das Tempo, ein Indoor-Cycling-Workout nicht).HKLiveWorkoutDataSourceist die Brücke von der Sensor-Konfiguration der Session zur Datenakkumulation des Builders. Die Datenquelle veröffentlicht Samples; der Builder empfängt und speichert sie.HKLiveWorkoutBuilderhält den Zustand des laufenden Workouts und finalisiert das gespeicherteHKWorkout-Objekt.
Das Muster ist inkrementell: Samples fließen kontinuierlich während des .running-Zustands; der Builder integriert sie in laufende Statistiken; der finale finishWorkout()-Aufruf schreibt das vollständige Workout in HealthKit.
iOS 26: Workouts auf dem iPhone
iOS 26 brachte HKWorkoutSession auf das iPhone mit demselben HKLiveWorkoutBuilder und derselben Datenquelle, API watchOS verwendet4. Die Konstruktion ist identisch; die plattformspezifischen Unterschiede liegen im Runtime-Modell, in der Sensorverfügbarkeit und im Datenschutz, nicht in der API-Oberfläche.
Die Anwendungsfälle, die das Workout-API von iOS 26 ermöglicht: - Phone-as-Companion-Workout-Apps (das iPhone hält Herzfrequenz-Monitor-Daten neben der Watch-Session). - iPhone-only-Fitness-Apps für Benutzer ohne Apple Watch, bei denen das iPhone die Session über eingebaute Sensoren und verbundenes Zubehör trackt. - Geräteübergreifende Session-Kontinuität: eine Apple-Watch-Session, die an das iPhone übergibt (der Benutzer nimmt die Watch ab, möchte aber, dass das iPhone weiter trackt) oder umgekehrt.
Die Plattform-Unterschiede, die Erwähnung verdienen: - Sensorverfügbarkeit. Das iPhone hat einen Beschleunigungssensor und GPS, aber keinen eingebauten Herzfrequenzsensor. Apps, die bei iOS-Workouts Herzfrequenz benötigen, koppeln sich mit einem Bluetooth-Herzfrequenzgurt oder lesen über HealthKit von einer verbundenen Apple Watch. - Runtime-Modell. Die Workout-Active-Runtime der Apple Watch garantiert kontinuierlichen Sensorzugriff während des Wrist-Drop. Die Runtime des iPhones stützt sich auf den normalen Vordergrund-/Hintergrund-Lebenszyklus des Systems plus Crash-Recovery über den Scene Delegate (behandelt in WWDC 2025 Session 322), was eine andere Garantieform ist. - Datenschutz und Lockscreen-Verhalten. iPhone-Workouts, die laufen, während das Gerät gesperrt ist, erfordern eine explizite Konfiguration, um weiterhin Samples zu sammeln, da der Sperrbildschirm eine stärkere Datenschutzgrenze darstellt als der Wrist-Drop.
Das Delegate-Protokoll
HKWorkoutSessionDelegate meldet Zustandsübergänge und Fehler5:
extension WorkoutCoordinator: HKWorkoutSessionDelegate {
func workoutSession(
_ workoutSession: HKWorkoutSession,
didChangeTo toState: HKWorkoutSessionState,
from fromState: HKWorkoutSessionState,
date: Date
) {
switch toState {
case .running:
// workout is active
case .paused:
// user paused
case .stopped:
// finalize metrics
case .ended:
// workout done; cleanup
default:
break
}
}
func workoutSession(
_ workoutSession: HKWorkoutSession,
didFailWithError error: Error
) {
// session failed (e.g., heart rate sensor disconnected unexpectedly)
}
}
Der Delegate ist die einzige Wahrheitsquelle für Zustandsübergänge. Apps, die den Zustand aus Methodenaufrufen ableiten („Ich habe startActivity() aufgerufen, also läuft jetzt das Workout”), verpassen Zustandsänderungen, die das System anwendet (Auto-Pause, wenn der Benutzer stillsteht, Auto-End, wenn die Watch abgenommen wird). Das delegate-getriebene Muster ist das richtige.
Der Runtime-Vertrag
HKWorkoutSession ist einer der Session-Typen, die watchOS anerkennt, um eine App im Hintergrund am Laufen zu halten — neben Mindfulness-, Alarm- und Audio-Aufnahme-Sessions6. Der Vertrag: Solange sich die Session in den Zuständen .prepared, .running, .paused oder .stopped befindet, läuft die App weiter; der Bildschirm aktiviert sich, wenn der Benutzer das Handgelenk hebt; Sensoren streamen kontinuierlich Daten an die App.
Der Beitrag watchOS Runtime Contract des Clusters behandelt dies im Detail. Der für Workout-Apps relevante Punkt: Der Lebenszyklus-Zustandsautomat ist das, was watchOS sagt „halte diese App am Laufen”; der Übergang zu .ended löst den Vertrag und erlaubt dem OS, die App zu suspendieren.
Eine praktische Implikation: Beenden Sie eine Workout-Session nicht vorzeitig. Wenn der Benutzer wegen eines Anrufs vom Workout weggeht und zurückkehrt, sollte die Session in .running bleiben (oder über pause() pausiert werden), nicht beendet werden. Beenden und Neustarten verliert die Daten und die Runtime-Kontinuität.
Häufige Fehler
Drei Muster aus Workout-App-Fehlerprotokollen:
prepare() überspringen. Apps, die startActivity(_:) aufrufen, ohne vorher prepare() aufgerufen zu haben, erzeugen Workouts, bei denen die ersten 5–10 Sekunden der Herzfrequenzdaten unzuverlässig sind (Sensor war nicht aufgewärmt) oder fehlen (Bluetooth-Herzfrequenzgurt hatte sich noch nicht verbunden). Lösung: Rufen Sie immer prepare() auf, zeigen Sie eine kurze Countdown-UI an und rufen Sie dann startActivity(_:) auf.
end() direkt aus .running aufrufen. Das Überspringen von .stopped überspringt das Fenster zur Metrik-Finalisierung. Der Live-Builder hat möglicherweise die finalen Samples nicht verarbeitet, bevor die Session terminiert, was zu fehlenden Zusammenfassungsstatistiken führt. Lösung: Rufen Sie immer zuerst stopActivity(_:) auf, warten Sie auf den Delegate-Callback, der .stopped bestätigt, und rufen Sie dann end() auf.
Den Zustand ableiten, statt den Delegate zu verwenden. Apps, die lokalen Zustand verfolgen (isWorkoutActive: Bool) und den Delegate nie verdrahten, verpassen system-getriebene Übergänge (Auto-Pause, Auto-End beim Abnehmen der Watch, Fehlerzustände). Lösung: Verwenden Sie immer den Delegate als Wahrheitsquelle.
Was dieses Muster für iOS-26+-Apps bedeutet
Drei Erkenntnisse.
-
Bilden Sie den Lebenszyklus explizit auf den UI-Zustand ab. Eine Workout-App-UI hat offensichtliche Zustände: Nicht gestartet, Vorbereitung, Aktiv, Pausiert, Zusammenfassung, Fertig. Bilden Sie jeden auf einen
HKWorkoutSessionStateab. Steuern Sie die UI nicht über ad-hoc Booleans; binden Sie sie an den vom Delegate gemeldeten Session-Zustand. -
Verwenden Sie
prepare()plus Countdown-UI für jede Session, die Metriken zeigt. Die 3-sekündige Aufwärmphase ist der Unterschied zwischen Daten, denen der Benutzer vertraut, und Daten, die der Benutzer abwertet. Die Kosten sind ein kleines UI-Element; der Gewinn sind verlässliche Metriken. -
iOS 26 iPhone-Workout-Sessions benötigen anderen Builder-Code. Die Session-API ist gemeinsam; die Builder-Seite ist plattformspezifisch. Apps, die einen Codepfad zwischen iOS und watchOS teilen, benötigen explizite
#if os(watchOS)-Verzweigungen oder einen Wrapper, der den Unterschied abstrahiert.
Der vollständige Apple-Ecosystem-Cluster: typisierte App Intents; MCP-Server; die Routing-Frage; Foundation Models; die Unterscheidung Runtime vs. Tooling-LLM; drei Oberflächen; das Single-Source-of-Truth-Muster; Zwei MCP-Server; Hooks für Apple-Entwicklung; Live Activities; die watchOS-Runtime; SwiftUI-Internals; RealityKits räumliches mentales Modell; SwiftData-Schema-Disziplin; Liquid-Glass-Muster; Multi-Plattform-Auslieferung; die Plattform-Matrix; Vision-Framework; Symbol Effects; Core-ML-Inferenz; Writing Tools API; Swift Testing; Privacy Manifest; Barrierefreiheit als Plattform; SF-Pro-Typografie; visionOS-Spatial-Muster; Speech-Framework; SwiftData-Migrationen; tvOS-Focus-Engine; @Observable-Internals; SwiftUI-Layout-Protokoll; benutzerdefinierte SF Symbols; AVFoundation HDR; worüber ich mich weigere zu schreiben. Der Hub befindet sich in der Apple Ecosystem Series. Für den breiteren Kontext von iOS mit AI-Agenten siehe den iOS Agent Development Guide.
FAQ
Verwendet das iPhone denselben HKLiveWorkoutBuilder wie die Apple Watch?
Ja, seit iOS 26. Derselbe HKLiveWorkoutBuilder API wird auf iOS 26+, iPadOS 26+, Mac Catalyst 26+ und watchOS 5+ ausgeliefert. Die Plattform-Unterschiede liegen im Runtime-Modell und in der Sensorverfügbarkeit, nicht in der Builder-API. iPhone-Workouts handhaben Datenschutz bei gesperrtem Bildschirm und Crash-Recovery über den Scene Delegate (gemäß WWDC 2025 Session 322), was sich von der Wrist-Drop-Runtime-Garantie von watchOS unterscheidet, aber die Datenakkumulations-API ist dieselbe.
Was ist die maximale Workout-Dauer?
Es gibt keine harte Dauerobergrenze. Praktische Grenzen ergeben sich aus dem Akku (Apple Watch hält ~6–8 Stunden bei kontinuierlichem Workout) und dem Speicher (Workouts mit hochfrequenten Daten akkumulieren schnell). Marathon-Lauf-Apps (12+ Stunden Workouts) werden heute ausgeliefert; das Framework unterstützt sie.
Wie handhabe ich Auto-Pause?
Setzen Sie HKWorkoutConfiguration.activityType auf einen Typ, der Auto-Pause unterstützt (z. B. .running). watchOS pausiert und setzt automatisch fort, basierend auf der Bewegung des Benutzers. Die Zustandsübergänge fließen durch den Delegate; behandeln Sie sie genauso wie vom Benutzer ausgelöste Pausen.
Was passiert, wenn der Benutzer mitten im Workout seine Watch abnimmt?
Die Session bleibt in ihrem aktuellen Zustand (typischerweise .running). Das watchOS-System wird die Session schließlich beenden, wenn die Watch zu lange vom Handgelenk entfernt ist; der didFailWithError-Callback des Delegates wird in diesem Fall ausgelöst. Apps mit geräteübergreifenden Sessions (iOS 26+) können an das iPhone übergeben, falls der Benutzer beide Geräte besitzt.
Sollte ich das Workout in HealthKit speichern?
Fast immer ja. Der Aufruf von builder.finishWorkout(completion:) schreibt das vollständige Workout in HealthKit, was bedeutet, dass die Daten in der Aktivitäts-App, der Workout-Liste der Health-App und in allen anderen Apps erscheinen, die der Benutzer autorisiert hat. Das Überspringen des Speicherns verwirft die Daten; das Framework bietet keinen Wiederherstellungspfad.
Wie verhält sich das zu anderen jüngsten Apple-Health-Ergänzungen?
iOS 26 / watchOS 26 erweiterte die Workout-API in zwei spezifischen Bereichen: erstens, indem HKWorkoutSession auf das iPhone gebracht wurde (oben behandelt); zweitens, durch die Erweiterung der Aktivitätstypliste und der Auto-Detection-Abdeckung. Der Beitrag watchOS Runtime Contract des Clusters behandelt die Runtime-Seite; dieser Beitrag behandelt die Lebenszyklus-Seite. Zusammen beschreiben sie die vollständige Oberfläche zum Ausliefern einer Workout-App.
Referenzen
-
Apple Developer Documentation:
HKWorkoutSession. Die Session-Klasse mit Zustandsübergängen, Konfiguration und dem Delegate-Protokoll. ↩↩ -
Apple Developer Documentation:
HKWorkoutSessionState. Die fünf Zustandsfälle (.notStarted,.prepared,.running,.paused,.stopped,.ended) und ihre Semantik. ↩↩ -
Apple Developer Documentation:
HKLiveWorkoutBuilderundHKLiveWorkoutDataSource. Der Live-Builder API (watchOS 5+, iOS 26+, iPadOS 26+, Mac Catalyst 26+) und seine Datenquelle. ↩↩ -
Apple Developer: Track workouts with HealthKit on iOS and iPadOS (WWDC 2025 Session 322). Die Erweiterung von
HKWorkoutSessionauf das iPhone in iOS 26. ↩ -
Apple Developer Documentation:
HKWorkoutSessionDelegate. Das Delegate-Protokoll mit Zustandsübergangs- und Fehler-Callbacks. ↩ -
Apple Developer Documentation: Background Execution on watchOS. Der watchOS-Runtime-Vertrag, der beschreibt, welche Session-Typen Apps während des Wrist-Drop am Laufen halten. ↩