Routing
is a library for separating navigation logic from SwiftUI views.
- De-couples navigation logic from SwiftUI views.
- Leads to better separation of concerns
- Requires iOS 16 or later.
You can install Routing
using the Swift Package Manager.
- In Xcode, select "File" > "Add Packages...".
- Copy & paste the following into the "Search or Enter Package URL" search bar.
https://github.com/obvios/Routing.git
- Xcode will fetch the repository & the "Routing" library will be added to your project.
- Create a
Routable
conformingEnum
to represent the different views you wish to route to.
import SwiftUI
import Routing
enum ExampleRoute: Routable {
case viewA
case viewB(String)
case viewC
@ViewBuilder
func viewToDisplay(router: Router<ExampleRoute>) -> some View {
switch self {
case .viewA:
ViewA(router: router)
case .viewB(let description):
ViewB(router: router, description: description)
case .viewC:
ViewC(router: router)
}
}
var navigationType: NavigationType {
switch self {
case .viewA:
return .push
case .viewB(_):
return .sheet
case .viewC:
return .fullScreenCover
}
}
}
- Wrap your view hierarchy in a
RoutingView
that is initialized with yourRoutable
enum. It will inject aRouter
instance into your root view.
import SwiftUI
import Routing
struct ContentView: View {
var body: some View {
RoutingView(ExampleRoute.self) { router in
RootView(router: router)
}
}
}
struct RootView: View {
@StateObject var router: Router<ExampleRoute>
init(router: Router<ExampleRoute>) {
_router = StateObject(wrappedValue: router)
}
var body: some View {
VStack() {
Button("View A") {
router.routeTo(.viewA)
}
Button("View B") {
router.routeTo(.viewB("Got here from RootView"))
}
Button("View C") {
router.routeTo(.viewC)
}
}
}
}
- Use the
Router
functions from any of your views. Here isViewA
which is pushed onto the navigation stack byRootView
.
struct ViewA: View {
@StateObject var router: Router<ExampleRoute>
init(router: Router<ExampleRoute>) {
_router = StateObject(wrappedValue: router)
}
var body: some View {
Text("View A")
Button("ViewC") {
router.routeTo(.viewC)
}
Button("Dismiss") {
router.dismiss()
}
}
}
The below articles are from my blog series explaining the Router
pattern and documents the progress of this library.