| name | navigator |
| description | Creates Navigator for navigation. Use when setting up navigation, adding navigation to ViewModels, or testing navigation behavior. |
Skill: Navigator
Guide for implementing navigation using NavigationCoordinator with SwiftUI NavigationStack, Navigator pattern for decoupling, and Outgoing/Incoming Navigation for cross-feature communication.
References
Architecture Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ RootContainerView โ
โ @State private var coordinator = NavigationCoordinator( โ
โ redirector: AppNavigationRedirect() โ
โ ) โ
โ โ
โ NavigationStack(path: $coordinator.path) { ... } โ
โ .sheet(item: $coordinator.sheetNavigation) { modal in โ
โ ModalContainerView(modal:appContainer:onDismiss:) โ
โ } โ
โ .fullScreenCover(item: $coordinator.fullScreenCoverNavigation) { ... } โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Push Navigation Flow:
1. HomeNavigator.navigateToCharacters()
2. coordinator.navigate(to: HomeOutgoingNavigation.characters)
3. AppNavigationRedirect.redirect() โ CharacterIncomingNavigation.list
4. NavigationStack shows CharacterListView
Modal Navigation Flow:
1. Navigator.presentFilter()
2. coordinator.present(Navigation.filter, style: .sheet(detents: [.medium, .large]))
3. sheetNavigation is set โ .sheet(item:) activates
4. ModalContainerView creates its own NavigationCoordinator + NavigationStack
5. Modal can push internally or present nested modals
Navigation Types
| Type | Description | Implementation |
|---|
| Incoming | Destinations a feature can handle | {Feature}IncomingNavigation enum |
| Outgoing | Destinations a feature wants to navigate to | {Feature}OutgoingNavigation enum |
| Redirect | Connects Outgoing โ Incoming | AppNavigationRedirect in App layer |
Why? Features remain decoupled. Feature A doesn't import Feature B. The App layer connects them via redirects.
Navigator Pattern
ViewModels use Navigators instead of NavigatorContract directly. This:
- Decouples ViewModels from navigation implementation details
- Makes testing easier with focused mocks
- Provides semantic navigation methods
Key Difference:
- Internal navigation: Uses
{Feature}IncomingNavigation directly
- External navigation: Uses
{Feature}OutgoingNavigation (redirected by App layer)
Modal Navigation
| Style | Description |
|---|
.sheet(detents:) | Presents as a sheet with configurable detents (default: [.large]) |
.fullScreenCover | Presents as a full-screen cover |
present(_:style:) โ sets sheetNavigation or fullScreenCoverNavigation on the coordinator
dismiss() โ priority: fullScreenCover > sheet > parent onDismiss
File Structure
Libraries/Core/
โโโ Sources/Navigation/
โ โโโ NavigationCoordinator.swift
โ โโโ NavigatorContract.swift
โ โโโ NavigationRedirectContract.swift
โ โโโ Navigation.swift
โ โโโ AnyNavigation.swift
โ โโโ ModalPresentationStyle.swift
โ โโโ ModalNavigation.swift
โ โโโ DeepLinkHandler.swift
โโโ Mocks/
โโโ NavigatorMock.swift
AppKit/Sources/
โโโ AppContainer.swift
โโโ Presentation/
โโโ Navigation/AppNavigationRedirect.swift
โโโ Views/
โโโ NavigationContainerView.swift
โโโ RootContainerView.swift
โโโ ModalContainerView.swift
Features/{Feature}/
โโโ Sources/Presentation/
โ โโโ Navigation/
โ โ โโโ {Feature}IncomingNavigation.swift
โ โ โโโ {Feature}OutgoingNavigation.swift
โ โ โโโ {Feature}DeepLinkHandler.swift
โ โโโ {Screen}/
โ โโโ Navigator/
โ โ โโโ {Screen}NavigatorContract.swift
โ โ โโโ {Screen}Navigator.swift
โ โโโ Tracker/
โ โโโ {Screen}TrackerContract.swift
โ โโโ {Screen}Tracker.swift
โ โโโ {Screen}Event.swift
โโโ Tests/Unit/Presentation/
โโโ Navigation/{Feature}DeepLinkHandlerTests.swift
โโโ {Screen}/Navigator/{Screen}NavigatorTests.swift
Checklist
Core Setup
AppKit Configuration
Feature Implementation
Testing