I’m making an attempt to create a centralized router
for my SwiftUI app and hoped to make the most of the @Surroundings
function for this.
Whereas this won’t be the most effective design sample, I’m making an attempt to grasp why the next doesn’t work.
I begin by creating 3 routes
enum Route: String, Hashable {
case dwelling
case paywall
case login
}
I then create this view modifier to arrange my root view with a router:
struct RouterViewModifier: ViewModifier {
@State personal var router = Router()
@ViewBuilder
personal func routeView(for route: Route) -> some View {
change route {
case .login:
LoginView()
case .dwelling, .paywall:
Textual content(route.rawValue)
}
}
func physique(content material: Content material) -> some View {
NavigationStack(path: $router.path) {
content material
.surroundings(router)
.navigationDestination(for: Route.self) { route in
routeView(for: route)
}
}
}
}
extension View {
func withRouter() -> some View {
modifier(RouterViewModifier())
}
}
You may see the .surroundings(router)
in my code above the place I assume the router is being injected within the physique
perform
I then set my app up like so:
@important
struct SwiftUI_CoordinatorApp: App {
var physique: some Scene {
WindowGroup {
RootView()
.withRouter()
}
}
}
struct RootView: View {
@Surroundings(Router.self) var router: Router?
var physique: some View {
ZStack {
Textual content("Splash")
.onAppear {
DispatchQueue.important.asyncAfter(deadline: .now() + 2) {
router?.navigate(to: .login)
}
}
}
.body(maxWidth: .infinity, maxHeight: .infinity)
.background(.yellow)
}
}
struct LoginView: View {
@Surroundings(Router.self) var router: Router?
var physique: some View {
VStack {
Button("Login") {
router?.navigate(to: .dwelling)
}
}
.toolbar(.hidden)
.padding()
}
}
So my RootView
which serves as a splash display will get arrange and after 2 seconds, the router pushes
to the login view as anticipated.
Nevertheless, now as soon as I’m on the LoginView
, once I faucet the button nothing occurs and the router is nil.
This will get mounted if in my second code snippet the place I’ve personal func routeView(for route: Route) -> some View {
I add .surroundings(router)
– every little thing begins working as anticipated.
So that’s:
@ViewBuilder
personal func routeView(for route: Route) -> some View {
Group {
change route {
case .login:
LoginView()
case .dwelling, .paywall:
Textual content(route.rawValue)
}
}
.surroundings(router)
}
I do not get why I have to inject the router into the surroundings twice. Should not doing it as soon as on the content material within the navigation stack degree be sufficient for all subsequent views within the app to entry it except it’s faraway from the surroundings ?