I am trying out Navigator, and following NavigatorDemo project. I am building a scenario, where flow will be:
Onboarding -> Login -> Tab Views
User can also move like:
Onboarding -> Login -> Forgot Password -> TabView
and that's where i am getting issue. I am trying it with modular architecture, so forgot password is in separate module. To navigate to that module, I am using your Demo project approach of using a resolver. When i tap on forgot password inside LoginView, console logs are following:
Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C sending(SignIn.SignInExternalRoutes.forgotPassword) Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C receiving(SignIn.SignInExternalRoutes.forgotPassword) Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C performing(NavigatorUI.NavigationAction(name: "send(_:)", action: (Function)))
Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C sending(ForgotPassword.ForgetPasswordDestinations.forgotPassword) Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C receiving(ForgotPassword.ForgetPasswordDestinations.forgotPassword) Navigator A0E1497A-0EEB-4E6D-801A-3CCDF202479C pushing(ForgotPassword.ForgetPasswordDestinations.forgotPassword)
But I'm not navigated to forgot password. I am suspecting that issue might be that wrong navigator is trying to navigate this, but I am unable to drill down on it. I know, i m missing a very little detail, but cant seem to figure it out. Below is the code I am using.
NavigatorPOCApp.swift
struct ApplicationRootView: View {
var body: some View {
applicationView(AppResolver(navigator: applicationNavigator()))
}
func applicationView(_ resolver: AppResolver) -> some View {
RootAppView()
.navigationDestination(ForgetPasswordDestinations.self)
.onNavigationReceive { (destination: ForgetPasswordDestinations, navigator) in
navigator.navigate(to: destination)
return .auto
}
.onNavigationRoute(SignInExternalViewRouter())
.environment(\.navigator, resolver.navigator)
.environment(\.signInDependencies, resolver)
}
RootAppView.swift
struct RootAppView: View {
@StateObject var appState = AppState()
var body: some View {
switch appState.flow {
case .onboarding:
ManagedNavigationStack {
OnboardingView()
.navigationDestination(LoginDestinations.self)
}
.environmentObject(appState)
case .dashboard:
RootTabView()
.environmentObject(appState) // for logout trigger
case .login:
ManagedNavigationStack {
LoginView()
.navigationCheckpoint(KnownCheckpoints.login)
.navigationDestination(LoginDestinations.self)
}
.environmentObject(appState)
}
}
}
LoginView.swift
public struct LoginView: View {
@Environment(\.navigator) var navigator: Navigator
@EnvironmentObject var appState: AppState
@State private var name = ""
@Environment(\.signInDependencies) var resolver
public init() { }
public var body: some View {
VStack {
TextField("Enter username", text: $name)
.padding()
.border(Color.black)
Button("Move to dashboard") {
appState.flow = .dashboard
}
.buttonStyle(.borderedProminent)
Button("Move to forgot password") {
try? resolver.signInExternalRouter.route(to: .forgotPassword) **//Here i m trying to move to ForgotPassword Module via external route**
}
.buttonStyle(.borderedProminent)
}
}
}
SignInExternalViewRouter.swift
public struct SignInExternalViewRouter: NavigationRouteHandling {
@MainActor public func route(to route: SignInExternalRoutes, with navigator: Navigator) {
switch route {
case .forgotPassword:
navigator.perform(
.send(ForgetPasswordDestinations.forgotPassword)
)
}
}
}
SignInDependencies.swift
public protocol SignInDependencies: SignInModuleDependencies { }
public protocol SignInModuleDependencies {
@MainActor var signInExternalViewProvider: any NavigationViewProviding<SignInExternalViews> { get }
@MainActor var signInExternalRouter: any NavigationRouting<SignInExternalRoutes> { get }
}
public enum SignInExternalViews: NavigationViews {
case external
}
public enum SignInExternalRoutes: NavigationRoutes {
case forgotPassword
}
//Mocking Dependencies
protocol MockSignInDependencies: SignInDependencies {}
extension MockSignInDependencies {
// Mock a view we need to be provided from elsewhere
@MainActor public var signInExternalViewProvider: any NavigationViewProviding<SignInExternalViews> {
MockNavigationViewProvider()
}
// Mock a router
@MainActor public var signInExternalRouter: any NavigationRouting<SignInExternalRoutes> {
MockNavigationRouter()
}
}
public class MockSignInResolver: MockSignInDependencies {}
// Make our environment entry
extension EnvironmentValues {
@Entry public var signInDependencies: SignInDependencies = MockSignInResolver()
}
ForgetPasswordDestinations.swift
public enum ForgetPasswordDestinations: NavigationDestination, Codable {
case forgotPassword
public var body: some View {
ForgetPasswordDestinationsView(select: self)
}
}
public struct ForgetPasswordDestinationsView: View {
let select: ForgetPasswordDestinations
public var body: some View {
switch select {
case .forgotPassword:
ForgetPasswordView()
}
}
}