Why Senior iOS Developers Treat Enums as Architecture, Not Syntax
Here’s a pattern I’ve seen play out across dozens of codebases over the years:
A video player component starts simple. Then requirements grow. Someone adds isPlaying, then isPaused, then isBuffering. An error: Error? appears. Then currentItem: VideoItem?. Before long, you’ve got nested conditionals trying to handle every combination.
Then someone—usually the most senior engineer—says: “This is just a state machine. It should be an enum.”
The refactor collapses those booleans and optionals into clear states. Impossible states disappear. The compiler enforces what used to be assumptions.
Most developers use enums as labels. Seniors use enums as a design weapon.
Over 25 years building iOS apps, I’ve watched enums replace inheritance hierarchies, eliminate bug categories, and turn vague requirements into self-documenting architecture.
In this edition, we focus on the foundational senior-level enum patterns every architect should master.
Case-Less Enums: Using Swift’s Native Namespace Tool
The Problem:
I used to see this everywhere:

The private init() is a hint to humans, not the compiler. Someone can still break it with reflection, or a junior dev copies it without understanding and removes private because “the compiler complained.”
The Solution:
Swift gives you real compiler enforcement:

Why It Matters:
- Instantiation is syntactically impossible, not just discouraged
- Zero runtime overhead—no vtable, no heap allocation
- Intent is obvious to any iOS engineer
- This is how Swift’s standard library organizes CommandLine, Unicode, and entire subsystems
State Machines: Eliminating Boolean Soup
The Problem:

This creates multiple invalid state combinations. What does it mean when isLoading = true AND users != nil? Can you have an error AND be loading?
You’ve created edge cases that only appear in race conditions or weird network scenarios.
The Solution:

Now your UI logic becomes deterministic:

Why It Matters:
The compiler won’t let you ship half-baked state transitions. Every case is explicit. Every edge case is handled or the code doesn’t compile. This is architectural defense, not just cleaner code.
Pattern Matching: Beyond Switch Statements
The Pattern:
Most engineers learn pattern matching for switch, then never use it elsewhere.
Conditional unwrapping: swift if case .failure(let error) = state { handle(error) }
Filtering collections: swift for case .success(let data) in results { process(data) }
Early exits: swift guard case .success(let data) = state else { return } process(data)
Why It Matters:
No pyramids of if let, no optional chaining gymnastics. The code reads like plain English—"if this matches, bind the value and continue.“
Protocol-Oriented Enums: Polymorphism Without Inheritance
The Pattern:
Enums can behave like polymorphic objects without the inheritance baggage:

Why It Matters:
Add a new case and the compiler errors everywhere you forgot to handle it. That’s not a bug—that’s your safety net.
Compare this to class hierarchies where adding a new subclass is silent. Tests might catch it. Code review might catch it. Production definitely will.
Enums as Error Domains: Structure Your Failures
The Pattern:
Stop scattering error handling across your codebase:

Why It Matters:
- Type safety - Can’t accidentally compare wrong error types
- Domain modeling - Network errors stay in the network layer
- Behavioral logic - Retry logic lives with the error definition
- Testability - Mock specific error cases trivially
When you need to add telemetry or build an error dashboard three months later, you have structured data instead of string parsing nightmares.
The Philosophy: Make Invalid States Unrepresentable
The Core Principle:
Every time you reach for an optional or a boolean flag, ask yourself:
"Am I modeling state, or am I avoiding modeling state?”
Nine times out of ten, that optional is hiding an enum that wants to exist. That boolean is probably one case in a three-case state machine. Those two related properties are associated values on a single enum case.
What Enums Give You:
- Safety: The compiler prevents impossible states
- Intent: Code documents itself—logic is explicit
- Maintainability: Changes break at compile time, not runtime
- Clarity: State transitions become predictable flows
The Reality Check:
When you explain a video player to someone, you don’t say “well, isPlaying might be true, and currentTime might be non-zero, and error might be nil…”
You say: “It’s either idle, playing, paused, or failed.”
That’s an enum. You were always thinking in enums. Make your code reflect it.
Enums aren’t a feature—they’re an architectural mindset.
What’s Next: The Deep Patterns
This newsletter covered the foundation—the patterns you need to stop writing buggy state management code.
But there’s a whole level above this.
The Gumroad toolkit goes into production-grade architecture:
- Type-safe routing - Build entire navigation systems where invalid routes don’t compile
- Custom RawRepresentable - Domain models that serialize themselves correctly by design
- Recursive enums - File systems, expression parsers, ASTs—tree structures that the compiler validates
- Enum factories via protocols - Dynamic case construction without reflection
- Custom pattern matching - ~= operator overloading for domain-specific matching
- Generic async enums - Pipeline architectures for async/await flows
- Enum-driven reducers - State management patterns that scale to 100K+ line codebases
- CaseIterable automation - UI generation from enum definitions
- Real refactor case studies - Before/after architecture diagrams from production apps
If you’re writing SwiftUI or building anything more complex than a CRUD app, these patterns save months of technical debt.
Reply ENUMS to get notified for early access.
The difference between good code and great architecture is knowing when to reach for these tools. The toolkit teaches you both the how and the when.
Until next time,
Enums aren’t a feature—they’re an architectural mindset. Write code the compiler can verify. Everything else is just hope.
About Swift in Practice
Swift in Practice is a weekly newsletter exploring production-grade architectures, Apple frameworks, and the real decisions behind high-performance iOS apps.
📩 Subscribe for deep dives into enums and other swift tricks
👋 Author
Bruno Valente Pimentel — Senior iOS Architect & Consultant 25+ years building at the intersection of code, creativity, and communication.
Currently open to collaborations and senior roles focused on video infrastructure, streaming systems, and Apple Intelligence-driven media tools.
☕ Enjoying Swift in Practice? It's free and reader-supported. If an edition saved you some debugging time, you can buy me a coffee: https://buymeacoffee.com/swiftinpractice
Originally published as a Swift in Practice edition on LinkedIn. Comments and discussion happen there.