https://github.com/silkodenis/swiftui-navigation-coordinator
A lightweight SwiftUI Navigation Coordinator package that supports stack navigation and modal presentation.
https://github.com/silkodenis/swiftui-navigation-coordinator
coordinator dismiss example ios modal navigation pattern pop present push segue stack unwind unwind-segue xcodeproj
Last synced: about 1 year ago
JSON representation
A lightweight SwiftUI Navigation Coordinator package that supports stack navigation and modal presentation.
- Host: GitHub
- URL: https://github.com/silkodenis/swiftui-navigation-coordinator
- Owner: silkodenis
- License: apache-2.0
- Created: 2024-04-29T14:49:10.000Z (almost 2 years ago)
- Default Branch: main
- Last Pushed: 2024-09-08T08:55:25.000Z (over 1 year ago)
- Last Synced: 2025-01-17T16:14:43.095Z (about 1 year ago)
- Topics: coordinator, dismiss, example, ios, modal, navigation, pattern, pop, present, push, segue, stack, unwind, unwind-segue, xcodeproj
- Language: Swift
- Homepage:
- Size: 1.62 MB
- Stars: 1
- Watchers: 1
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
Awesome Lists containing this project
README
[](https://github.com/silkodenis/swiftui-navigation-coordinator/blob/main/LICENSE)

# SwiftUI Navigation Coordinator
## About the Project
This project provides a lightweight Navigation Coordinator, using SwiftUI NavigationStack (available from iOS 16).
## Core Features
The current implementation covers 6 main transitions:
Stack Navigation:
- `push` — navigates forward to a new view.
- `pop` — returns to the previous view.
- `unwind` — performs a multi-level return.
- `popToRoot` — returns to the root view.
Modal Presentation:
- `present` — displays a modal view, overlaying it on top of current content.
- `dismiss` — closes the current modal view and returns to the underlying content.
## Requirements
- **iOS**: iOS 16.0+
- **macOS**: macOS 13.0+
- **watchOS**: watchOS 9.0+
- **tvOS**: tvOS 16.0+
## Add with Swift Package Manager:
1. Open Xcode and select “File” > “Add Packages…”
2. Enter the URL of the package repository.
3. Follow the instructions to complete the installation.
## Getting Started
1. Configure the NavigableScreen Enum
Start by creating an enum Screen to represent the different screens in your app. Ensure it conforms to the NavigableScreen protocol:
```swift
import NavigationCoordinator
enum Screen {
case login
case movies
case settings
// etc.
}
extension Screen: NavigableScreen {
@ViewBuilder
var view: some View {
switch self {
case .login: LoginView()
case .movies: MoviesView()
case .settings: SettingsView()
}
}
}
```
2. Define Typealiases
Define typealias to simplify the usage of the types used with your coordinator:
```swift
import NavigationCoordinator
typealias SegueModifier = RegisterSegueModifier
typealias Coordinator = NavigationCoordinator
typealias RootView = NavigationStackRootView
```
3. Configure the App Entry Point
Set up the app entry point using the RootView to define the initial screen:
```swift
import SwiftUI
@main
struct MainApp: App {
var body: some Scene {
WindowGroup {
RootView(.login)
}
}
}
```
## Usage Examples
Push
```swift
import SwiftUI
struct LoginView: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("Movies") {
coordinator.push(.movies)
}
}
}
```
Pop
```swift
import SwiftUI
struct MoviesView: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("back") {
coordinator.pop()
}
}
}
```
PopToRoot
```swift
import SwiftUI
struct SettingsView: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("login") {
coordinator.popToRoot()
}
}
}
```
Unwind
Use a unique identifier for your unwind segues. If a segue becomes no longer relevant, it will be automatically removed from the coordinator. Using `onUnwind()` modifier is completely safe, tested, and does not involve any memory leaks or unintended calls.
```swift
import SwiftUI
// B View
// 🟦🟦🅰🟦🟦🟦🟦🟦🟦🅱️
struct B: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("pop to A") {
coordinator.unwind(to: "identifier" /*, with: Any?*/)
}
}
}
// A View
// 🟦🟦🅰️
struct A: View {
var body: some View {
VStack {}
.onUnwind(segue: "identifier") /*{ Any? in }*/
}
}
```
`onUnwind()` will always be called before `onAppear()`.
Present
```swift
import SwiftUI
/*
[B]
[ ][ ][ ][ ][ ][A]
*/
struct A: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("present") {
coordinator.present(.B)
}
}
}
```
Dismiss
```swift
import SwiftUI
/*
[B][ ][ ][ ][CL]
[ ][ ][ ][ ][ ][A]
*/
struct CL: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("dismiss") {
coordinator.dismiss(/*to: "identifier" /*, with: Any?*/*/)
}
}
}
/*
[ ][ ][ ][ ][ ][A]
*/
struct A: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
VStack {}
// Not necessary. Only if you need to capture an onDismiss event.
.onDismiss(segue: "identifier") /*{ Any? in }*/
}
}
```
## Project examples
- [Original Example](https://github.com/silkodenis/swiftui-navigation-coordinator/tree/main/Example)
- [SwiftUI Redux TMDB Demo App](https://github.com/silkodenis/swiftui-moviesdb-redux-app)
## Reporting Issues
I welcome any issues you find within the project. If you encounter bugs or have suggestions for improvements, please feel free to create an issue on the GitHub repository.
## License
**Apache License 2.0**. See the [LICENSE](https://github.com/silkodenis/swiftui-navigation-coordinator/blob/main/LICENSE) file for details.