A professional-grade navigation architecture for SwiftUI applications that implements a robust, scalable navigation system with state persistence, deep linking, and notification handling.
- Centralized Navigation Management: Route-based navigation with a type-safe API
- State Persistence: Navigation stack is preserved across app restarts
- Deep Linking: Full support for custom URL schemes and launching to specific screens
- Associated Values: Pass data between views in a type-safe manner
- Notification Navigation: Handle push notifications that navigate to specific app sections
- Auth-Aware Navigation: Conditional navigation flows based on authentication state
- iOS 17.0+
- Xcode 15.0+
- Swift 5.9+
The central navigation controller that manages the navigation stack and provides navigation APIs:
// Navigate to a specific screen
router.navigate(to: .profile(userId: "123"))
// Go back one level
router.goBack()
// Pop to root
router.popToRoot()
// Replace entire stack
router.setNavigationStack(with: [.dashboard, .settings(initialSection: "privacy")])A type-safe representation of all navigable destinations with associated values:
enum Route: Hashable, Codable {
case onboarding
case login
case register
case dashboard
case profile(userId: String? = nil)
case settings(initialSection: String? = nil)
case setup
case verify(email: String)
case questionnaire(step: Int = 1)
// ...
}The root view that conditionally displays content based on app state and handles navigation destinations.
Manages application-level state like authentication and onboarding status.
- The app starts with
ContentViewwhich applies theRouterViewModifier RouterViewModifiercreates the Router and AppState, injecting them into the environmentNavigationContainerdisplays the appropriate root view based on app state- Navigation events are processed by the Router, which updates the NavigationPath
- The NavigationStack responds to path changes and displays the appropriate views
The app supports deep linking with the navapp:// custom URL scheme:
navapp://profile?userId=123456
navapp://settings?section=privacy
navapp://questionnaire?step=2
navapp://verify?email=user@example.com
Deep links can be processed when the app is launched from a URL or when it's already running.
The notification system can:
- Display local notifications with quiz questions
- Handle notification taps to navigate to specific app sections
- Process notifications whether the app is in foreground, background, or terminated
The system consists of:
NotificationManager: Handles sending notifications and permission requestsNotificationHandler: Processes notification responses and triggers navigationAppDelegate: Captures system-level notification events
Navigation state is automatically saved to UserDefaults and restored when the app launches, allowing users to resume exactly where they left off, even with complex navigation paths containing associated values.
// In any view with access to the Router
@Environment(Router.self) private var router
// Navigate to a new screen
router.navigate(to: .profile(userId: "123"))
// Go back
router.goBack()if appState.isAuthenticated {
router.navigate(to: .dashboard)
} else {
router.navigate(to: .login)
}// When a notification is tapped
func userNotificationCenter(_ center: UNUserNotificationCenter,
didReceive response: UNNotificationResponse) {
if let step = response.notification.request.content.userInfo["step"] as? Int {
// Navigate to specific questionnaire step
router.setNavigationStack(with: [.dashboard, .questionnaire(step: step)])
}
}- Use associated values to pass minimal context between views
- Leverage the Router's API rather than manipulating NavigationPath directly
- Apply appropriate authentication checks before navigation
- Use the deep linking system for both external URLs and internal app navigation
- The Router uses SwiftUI's NavigationStack and NavigationPath for navigation
- Enum associated values enable type-safe parameter passing
- Custom Codable implementation ensures state persistence works with associated values
- ScenePhase monitoring handles application lifecycle events correctly
This project uses the MIT license. See LICENSE for details.
Created by Junaed Muhammad Chowdhury © 2025