How I Handle State Management in a Health App
State in a Breathing App Is Deceptively Complex On the surface, Lunair seems like it would have simple state: a breathing pattern is playing or it is not. In reality, the state graph is surprisingl...

Source: DEV Community
State in a Breathing App Is Deceptively Complex On the surface, Lunair seems like it would have simple state: a breathing pattern is playing or it is not. In reality, the state graph is surprisingly deep once you account for interruptions, background transitions, accessibility events, and user preferences. The State Machine Approach Early on I used a collection of boolean flags — isPlaying, isPaused, isComplete. This quickly devolved into impossible states. Could something be both paused and complete? The flags said yes; reality said no. I switched to an explicit state machine: enum SessionState: Equatable { case idle case preparing(pattern: BreathPattern) case active(phase: BreathPhase, cycleCount: Int) case paused(resumePhase: BreathPhase, cycleCount: Int) case completing(totalCycles: Int) case completed(summary: SessionSummary) } Every possible state is explicitly modeled. The paused case carries the information needed to resume. The completing state handles the wind-down animation