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.