Skip to content

macogurumi/KGBNavigator

Repository files navigation

KGBNavigator

KGBNavigator is a function-based navigation library for SwiftUI that provides a scalable and type-safe way to manage navigation in your application. It uses UIKit's UINavigationController under the hood to give you precise control over the navigation stack, while allowing you to write your views in SwiftUI.

Features

  • Function-Based Navigation: Navigate using simple function calls like navigator.navigateToProfile(userId: ...).
  • Compile-Time Safety: Avoid runtime errors with compile-time checks for navigation destinations and parameters.
  • Scalable: Designed to support large applications with many screens and modules without a centralized router.
  • Decoupled: Keeps navigation logic separate from your view logic.
  • UIKit Power, SwiftUI Simplicity: Leverages UINavigationController for robust navigation and UIHostingController to use SwiftUI views.

Architecture

The library is built around three main components:

  1. NavigationContext: A wrapper around UINavigationController that provides simple push, present, pop, and dismiss methods for SwiftUI views.
  2. Navigator: A protocol that defines a navigator. Each feature or module in your app will have its own navigator.
  3. Scoped Navigators: Concrete implementations of the Navigator protocol (e.g., HomeNavigator, ProfileNavigator) that define the specific navigation functions for a feature.

How to Use

1. Setup the Root View

In your SceneDelegate, set up the HostingNavigationController, NavigationContext, and the initial view and navigator.

import UIKit
import SwiftUI
import KGBNavigator

class SceneDelegate: UIResponder, UIWindowSceneDelegate {

    var window: UIWindow?

    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        guard let windowScene = (scene as? UIWindowScene) else { return }
        
        let window = UIWindow(windowScene: windowScene)
        
        let navController = HostingNavigationController()
        let context = NavigationContext(navController: navController)
        let homeNavigator = HomeNavigator(context: context)
        let rootView = HomeView(navigator: homeNavigator)
        
        navController.setViewControllers([UIHostingController(rootView: rootView)], animated: false)
        
        window.rootViewController = navController
        self.window = window
        window.makeKeyAndVisible()
    }
}

2. Create Navigators

Create a navigator for each feature module.

HomeNavigator.swift

import Foundation
import KGBNavigator

final class HomeNavigator: Navigator {
    let context: NavigationContext

    init(context: NavigationContext) {
        self.context = context
    }

    func navigateToProfile(userId: UUID) {
        let profileNavigator = ProfileNavigator(context: context)
        let view = ProfileView(userId: userId, navigator: profileNavigator)
        context.push(view)
    }
}

ProfileNavigator.swift

import Foundation
import KGBNavigator

final class ProfileNavigator: Navigator {
    let context: NavigationContext

    init(context: NavigationContext) {
        self.context = context
    }
    
    func goBack() {
        context.pop()
    }
}

3. Create Views

Create your SwiftUI views and pass the navigator to them.

HomeView.swift

import SwiftUI

struct HomeView: View {
    let navigator: HomeNavigator

    var body: some View {
        VStack {
            Text("Home View")
                .padding()
            Button("Go to Profile") {
                navigator.navigateToProfile(userId: UUID())
            }
        }
        .navigationTitle("Home")
    }
}

ProfileView.swift

import SwiftUI

struct ProfileView: View {
    let userId: UUID
    let navigator: ProfileNavigator

    var body: some View {
        VStack {
            Text("Profile View")
                .padding()
            Text("User ID: \(userId.uuidString)")
                .padding()
            Button("Go Back") {
                navigator.goBack()
            }
        }
        .navigationTitle("Profile")
    }
}

Installation

Add KGBNavigator as a dependency to your Package.swift file:

dependencies: [
    .package(url: "https://github.com/your-username/KGBNavigator.git", from: "1.0.0")
]

About

UIKit navigation system for SwiftUI view

Resources

Stars

Watchers

Forks

Packages

No packages published

Languages