Skip to content

Junaed29/SwiftUI_NavigationControl

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

9 Commits
 
 
 
 
 
 

Repository files navigation

NavigationSetup - Modern SwiftUI Navigation Architecture

A professional-grade navigation architecture for SwiftUI applications that implements a robust, scalable navigation system with state persistence, deep linking, and notification handling.

Features

  • 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

Requirements

  • iOS 17.0+
  • Xcode 15.0+
  • Swift 5.9+

Architecture Overview

Core Components

Router Class

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")])

Route Enum

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)
    // ...
}

NavigationContainer

The root view that conditionally displays content based on app state and handles navigation destinations.

AppState

Manages application-level state like authentication and onboarding status.

Navigation Flow

  1. The app starts with ContentView which applies the RouterViewModifier
  2. RouterViewModifier creates the Router and AppState, injecting them into the environment
  3. NavigationContainer displays the appropriate root view based on app state
  4. Navigation events are processed by the Router, which updates the NavigationPath
  5. The NavigationStack responds to path changes and displays the appropriate views

Deep Linking

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.

Notification Handling

The notification system can:

  1. Display local notifications with quiz questions
  2. Handle notification taps to navigate to specific app sections
  3. Process notifications whether the app is in foreground, background, or terminated

The system consists of:

  • NotificationManager: Handles sending notifications and permission requests
  • NotificationHandler: Processes notification responses and triggers navigation
  • AppDelegate: Captures system-level notification events

State Persistence

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.

Usage Examples

Basic Navigation

// 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()

Conditional Navigation Based on Auth State

if appState.isAuthenticated {
    router.navigate(to: .dashboard)
} else {
    router.navigate(to: .login)
}

Deep Linking from Notifications

// 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)])
    }
}

Best Practices

  • 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

Implementation Details

  • 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

License

This project uses the MIT license. See LICENSE for details.


Created by Junaed Muhammad Chowdhury © 2025

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages