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: 3 months 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 (about 1 year ago)
- Default Branch: main
- Last Pushed: 2024-09-08T08:55:25.000Z (9 months ago)
- Last Synced: 2025-01-17T16:14:43.095Z (4 months 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 NavigationCoordinatorenum 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 NavigationCoordinatortypealias 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 SwiftUIstruct LoginView: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("Movies") {
coordinator.push(.movies)
}
}
}
```Pop
```swift
import SwiftUIstruct MoviesView: View {
@EnvironmentObject var coordinator: Coordinator
var body: some View {
Button("back") {
coordinator.pop()
}
}
}
```PopToRoot
```swift
import SwiftUIstruct 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.