What is Navigation?
Navigation in TCA is broadly defined as a change of mode in the application. This includes drill-downs, sheets, popovers, alerts, confirmation dialogs, and any other UI transition where state goes from not existing to existing (or vice-versa). State-driven navigation falls into two main categories:Tree-based Navigation
Navigation modeled with optionals and enums
Stack-based Navigation
Navigation modeled with flat collections
Defining Navigation
For TCA purposes, we use the following definitions:Navigation is a change of mode in the application.Change of mode is when some piece of state goes from not existing to existing, or vice-versa.
Tree-based Navigation
Tree-based navigation uses Swift’sOptional type to represent the existence or non-existence of state. When multiple states are nested, they form a tree-like structure.
Example
Suppose you have an inventory feature that can drill down to a detail screen:Deep Linking
With tree-based navigation, deep-linking is simply constructing deeply nested state:Read the dedicated Tree-based Navigation article for detailed implementation guidance.
Stack-based Navigation
Stack-based navigation models the presentation of features using collections. This is most commonly used with SwiftUI’sNavigationStack, where an entire stack of features is represented by a collection of data.
Example
Define an enum holding all possible features that can be navigated to:Read the dedicated Stack-based Navigation article for detailed implementation guidance.
Comparing Approaches
Most applications use a mixture of both approaches. Here’s how they compare:Tree-based Navigation
Pros
Pros
- Concise modeling: Statically describe all valid navigation paths, making invalid states impossible
- Finite navigation paths: Enforces relationships between screens (e.g., edit only accessible from detail)
- Better modularity: Feature modules are self-contained with fully functional previews
- Easier integration testing: Tight integration makes unit testing interactions straightforward
- API unification: Single style handles drill-downs, sheets, popovers, alerts, dialogs, and more
Cons
Cons
- Recursive paths are difficult: Complex navigation patterns (like movie → actor → movie) create recursive dependencies
- Couples features together: Must compile all destination features to compile the parent feature
- More SwiftUI bugs historically: Though many fixed in iOS 16.4+
Stack-based Navigation
Pros
Pros
- Handles complex navigation: Easily supports recursive and complex navigation paths
- Decouples features: Features can be in separate modules with no dependencies on each other
- Fewer SwiftUI bugs:
NavigationStackAPI is generally more stable
Cons
Cons
- Not concise: Can express nonsensical navigation paths (e.g., edit before detail)
- Inert isolated previews: Features in isolation can’t navigate to other features
- Harder integration testing: Difficult to test how features interact when fully decoupled
- Limited scope: Only applies to drill-downs, not sheets, popovers, alerts, etc.
Next Steps
Tree-based Navigation
Learn about navigation with optionals and enums
Stack-based Navigation
Learn about navigation with collections