Issue #830
Since iOS 16, it is possible to define programmatic routes with `NavigationStack
I usually start by defining enum Route
for all possible routes in the app. Note if your app is complex, you can define multiple Route type, each for different use case
enum Route: Hashable {
case authors
case books
case search
case settings
}
The benefit of using Route is decoupling. In a few places where we pass ObservableObject
or Binding
to the next navigated view, we have to think twice when we convert them to Route
as it requires parameters to be of Hashable
Define a view to switch on Route
struct RouteView: View {
let route: Route
var body: some View {
switch route {
case .authors:
AuthorsView()
case .books:
BooksView()
case .search:
SearchView()
case .settings:
SettingsView()
}
}
}
Use a Router
object to hold on an array of routes
final class Router: ObservableObject {
@Published var routes: [Route] = []
func navigate(to route: Route) {
routes.append(route)
}
}
Declare Router
for each navigation stack, and inject Router
object inside environment so we can access it anywhere in the environment path
struct CompactView: View {
@StateObject private var booksRouter = Router()
var body: some View {
TabView {
NavigationStack(path: $booksRouter.routes) {
BooksView()
.navigationDestination(for: Route.self) {
RouteView(route: route)
.environmentObject(booksRouter)
}
}
.environmentObject(booksRouter)
}
}
}
Note that we need to inject environmentObject
inside navigationDestination
too
Read more
Router
- https://davidgarywood.com/writing/swiftui-router-pattern/
- https://github.com/roboheadz/swiftui-router
Coordinator