A powerful SwiftUI navigation framework that provides a clean, coordinator-based architecture for managing complex navigation flows in iOS applications.
π View Documentation Site | π Full Documentation
- iOS 16.0+
- Swift 5.10+
- Xcode 15.0+
Add NavigationKit to your Swift Package Manager dependencies:
dependencies: [
.package(url: "https://github.com/dimzfresh/NavigationKit.git", from: "1.0.0")
]NavigationKit is built around a coordinator pattern that provides a clean separation of concerns between navigation logic and view presentation. The framework consists of several key components:
The foundation of the navigation system. Every coordinator implements this protocol:
@MainActor
public protocol Coordinator: ObservableObject, CoordinatorFinishDelegate {
associatedtype Content: View
@MainActor @ViewBuilder var rootView: Content { get }
var finishDelegate: CoordinatorFinishDelegate? { get set }
func finish()
}Extends the basic coordinator with navigation capabilities:
@MainActor
public protocol BaseCoordinator: Coordinator {
var childCoordinator: (any Coordinator)? { get set }
var navigationRouters: [NavigationRouter] { get set }
}Manages the navigation stack and presentation state:
@MainActor
public final class NavigationRouter: ObservableObject {
@Published var path: [NavigableView] = []
@Published var presentedView: NavigableView?
}Represents a view that can be navigated to:
public struct NavigableView: Navigable {
public let view: any View
public let navigationType: NavigationType
}NavigationKit supports multiple navigation patterns:
- Push Navigation: Standard stack-based navigation
- Sheet Presentation: Modal presentation with customizable detents
- Full Screen Cover: Full-screen modal presentation
- Custom Presentation: Custom presentation styles
public enum NavigationType: Equatable {
case push
case present(PresentationType)
}
public enum PresentationType: Equatable {
case sheet(Set<PresentationDetent> = [])
case fullScreen
case custom
}βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
β NavigationKit Architecture β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββ βββββββββββββββββββ β
β β Coordinator β β BaseCoordinator β β
β β (Protocol) ββββββ€ (Protocol) β β
β βββββββββββββββββββ βββββββββββββββββββ β
β β β β
β β βΌ β
β β βββββββββββββββββββ β
β β βNavigationRouter β β
β β β (Class) β β
β β βββββββββββββββββββ β
β β β β
β β βΌ β
β β βββββββββββββββββββ β
β β β NavigableView β β
β β β (Struct) β β
β β βββββββββββββββββββ β
β β β β
β β βΌ β
β β βββββββββββββββββββ β
β β β NavigationType β β
β β β (Enum) β β
β β βββββββββββββββββββ β
β β β β
β β βΌ β
β β βββββββββββββββββββ β
β β βPresentationType β β
β β β (Enum) β β
β β βββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β Deep Link Support β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ€
β β
β βββββββββββββββββββ βββββββββββββββββββ β
β β DeepLink β βDeepLinkCoordinatorβ β
β β (Protocol) ββββββ€ (Class) β β
β βββββββββββββββββββ βββββββββββββββββββ β
β β
βββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββββ
@MainActor
final class MainCoordinator: BaseCoordinator {
@Published var childCoordinator: (any Coordinator)?
@Published var navigationRouters: [NavigationRouter] = []
var rootView: some View {
NavigationStack(path: rootNavigationRouter.pathBinding) {
HomeView()
.navigationDestination(for: NavigableView.self) { navigableView in
navigableView.view
}
}
.sheet(isPresented: shouldPresentChild(from: rootNavigationRouter)) {
if let childCoordinator {
childCoordinator.rootView
}
}
.onAppear {
setupNavigationRouter()
}
}
}// Push to a new view
let detailView = NavigableView(
view: DetailView(),
navigationType: .push
)
push(detailView)
// Present a sheet
let settingsView = NavigableView(
view: SettingsView(),
navigationType: .present(.sheet())
)
push(settingsView)
// Present full screen
let loginView = NavigableView(
view: LoginView(),
navigationType: .present(.fullScreen)
)
push(loginView)struct ProductDeepLink: DeepLink {
func canOpenURL(_ url: URL) -> Bool {
return url.scheme == "myapp" && url.host == "product"
}
func openURL(_ url: URL) {
// Handle product deep link
let productId = url.queryParameters?["id"] ?? ""
// Navigate to product detail
}
}
let deepLinkCoordinator = DeepLinkCoordinator(deepLinks: [
ProductDeepLink()
])
// Handle incoming URLs
func application(_ app: UIApplication, open url: URL) -> Bool {
return deepLinkCoordinator.handleURL(url)
}- Coordinator Pattern: Clean separation of navigation logic
- Type-Safe Navigation: Compile-time safety for navigation operations
- Multiple Presentation Styles: Support for push, sheet, and full-screen presentations
- Deep Link Support: Built-in deep link handling
- SwiftUI Native: Designed specifically for SwiftUI
- iOS 16+ Support: Leverages the latest SwiftUI features
- MainActor Compliance: Thread-safe navigation operations
- Fork the repository
- Create a feature branch
- Make your changes
- Add tests if applicable
- Submit a pull request
This project is licensed under the MIT License - see the LICENSE file for details.