iosswiftswiftui

SwiftUI NavigationStack - Why Does View State Persist When Navigating Back and Forth?


I have a navigation hierarchy structured like this:

Root View -> View A -> View B -> View C -> View D
RootView() .navigationDestination(
                for: DashboardDestinations.self,
                destination: { screen in
                    switch screen {
                    case .ScreenA:
                        ScreenA()
                    case .ScreenB:
                        ScreenB()
                })
        }
class DashboardRouter: ObservableObject {
   var path = NavigationPath()

  static let shared: DashboardRouter = DashboardRouter()

  func popToRoot() {
    path = NavigationPath()
  }

  func popToView B() {
    path = NavigationPath([DashboardDestinations.ViewA, DashboardDestinations.ViewB])
  }
}

In my DashboardRouter class, I manage navigation using a NavigationPath.

When I’m in View D and trigger a button to go back to View B by resetting the navigation path:

DashboardRouter.shared.popToViewB()

and then navigate forward again to View C, I notice that View C’s state is preserved from the previous time it was shown, instead of being reset.

Why does the state of View C persist after popping back to View B and navigating forward again? How can I make sure View C resets its state when I navigate to it again?


Solution

  • Try this way I have implemented same below method in one of my app which removes destination from NavigationPath completely and resets state.

    
    final class Router: ObservableObject {
        
        public enum Destination: Codable, Hashable {
            case screenA
            case screenB
            case screenC
            case screenD
        }
        
        @Published var navPath = NavigationPath()
        
        func navigate(to destination: Destination) {
            navPath.append(destination)
        }
        
        func navigateBack() {
            navPath.removeLast()
            
        }
        
        func navigateToRoot() {
            navPath.removeLast(navPath.count)
            
        }
        
        func navigateToScreenB() {
            navPath.removeLast(navPath.count)
            navPath.append(Destination.screenA)
            navPath.append(Destination.screenB)
        }
        
    }