nalexn / clean-architecture-swiftui

SwiftUI sample app using Clean Architecture. Examples of working with CoreData persistence, networking, dependency injection, unit testing, and more.
MIT License
5.83k stars 709 forks source link

Reseting route state #78

Closed MohsenKhosravinia closed 5 months ago

MohsenKhosravinia commented 2 years ago

Hit @nalexn, great job on you repo. I have a question. How and when do you reset your routing states? Currently I have a hierarchy like below: SplashView -> AuthenticationView -> SignUpView -> HomeView I want to log out on home view and go back (move forward) to authentication view. when I change the routing state on home view and go to authentication view, all the previous flags for navigation are true and therefore the view goes forward again and again.

nalexn commented 2 years ago

Hey,

How and when do you reset your routing states?

If we're talking about a real "reset" of the state, there is one place I do this to essentially restart the app after appearance settings are changed by EnvironmentOverrides panel (a UI/UX testing tool I built, which is also demoed as part of this project).

Normally you don't want a full reset, but toggle a few flags at once to pop back to your AuthenticationView. That is, there should be a flag that presented SignUpView and another one that displayed HomeView, so as soon as you toggle both off you should be good.

If this tip does not help, please do provide the code of how you're changing the routing state to pop back and the routing state structure itself.

MohsenKhosravinia commented 2 years ago

@nalexn Would you please take a look at this project? https://gitlab.com/MohsenKhosravinia/cleanarchvaiyo

nalexn commented 2 years ago

Ok, after a quick glance I think you should remove NavigationLink here and leave just the Button:

NavigationLink(destination: AuthenticationView(), isActive: routingBinding.shouldNavigateToAuthetication) {
    Button {
        logout()
    } label: {
        Image(systemName: "power")
            //...
    }
}

then, I'd removed the var shouldNavigateToAuthetication: Bool = false in the HomeView.Routing. In your logout, instead of

injected.appState[\.routing.home.shouldNavigateToAuthetication] = true

you should toggle the container.interactors.splashInteractor.isLogin, since I can see it toggles between AuthenticationView and HomeView:

if container.interactors.splashInteractor.isLogin {
    NavigationLink(
        destination: HomeView(),
        isActive: $showHomeView) { EmptyView() }
} else {
    NavigationLink(
        destination: AuthenticationView(),
        isActive: $showAuthenticationView) { EmptyView() }
}
MohsenKhosravinia commented 2 years ago

Thank you for the effort but I want to go forward (after log out I want to instantiate new authentication view). I did follow your steps but the log out button does nothing without navigation link. When we instantiate a view twice (based on a UX situation) we don't get the proper result because the app state holds the routing last states and the automatic navigation happens afterward. Do you have any suggestion on that? I was trying to reset the AppState.Routing struct on the .onAppear or .onDisappear but the result was messy and not satisfying.

nalexn commented 2 years ago

Ok, then if you actually need to show another AuthenticationView and not pop back to the original, the second one has to rely on separate routing parameters. Introduce a secondary set of routing params for AuthenticationView, and then control which set to use by providing an enum or a bool value as init parameter for the AuthenticationView