Search code examples
swiftuiswiftui-navigationlinkswiftui-navigationview

SwiftUI NavigationView Coordinator Issue


I made an example to demonstrate how I tried to exclude navigation states from views. The problem is that somehow storing the navigation states in an ObservableObject breaks navigation. After tapping the "Show SecondDetailView" NavigationLink, the SecondDetailView is shown for a very short time and then the view pops away.

Can someone explain why navigation to SecondDetailView is not working?

class NavigationCoordinator: ObservableObject {
    
    @Published var showFirstDetailView: Bool = false
    @Published var showSecondDetailView: Bool = false
    @Published var showThirdDetailView: Bool = false
}

struct MainView: View {
  
    @StateObject
    var navigationCoordinator: NavigationCoordinator = NavigationCoordinator()

    var body: some View {
        
        NavigationView {
            VStack {
                Text("MainView").font(.headline)
                Text("showFirstDetailView: \(navigationCoordinator.showFirstDetailView.description)")
                NavigationLink(isActive: $navigationCoordinator.showFirstDetailView, destination: {FirstDetailView()}, label: {Text("Show FirstDetailView")})
            }
        }
        .environmentObject(navigationCoordinator)
    }
}

struct FirstDetailView: View {
    
    @EnvironmentObject
    var navigationCoordinator: NavigationCoordinator

    var body: some View {
        VStack {
            Text("FirstDetailView").font(.headline)
            Text("showSecondDetailView: \(navigationCoordinator.showSecondDetailView.description)")
            NavigationLink(isActive: $navigationCoordinator.showSecondDetailView, destination: {SecondDetailView()}, label: {Text("Show SecondDetailView")})
        }
    }
}

struct SecondDetailView: View {
    
    @EnvironmentObject
    var navigationCoordinator: NavigationCoordinator

    var body: some View {
        VStack {
            Text("SecondDetailView").font(.headline)
            Text("showThirdDetailView: \(navigationCoordinator.showThirdDetailView.description)")
            NavigationLink(isActive: $navigationCoordinator.showThirdDetailView, destination: {ThirdDetailView()}, label: {Text("Show ThirdDetailView")})
        }
    }
}

struct ThirdDetailView: View {
    
    @EnvironmentObject
    var navigationCoordinator: NavigationCoordinator
    
    var body: some View {
        Text("ThirdDetailView").font(.headline)
    }
}

struct MainView_Previews: PreviewProvider {
    static var previews: some View {
        MainView()
    }
}

Solution

  • don't know why the SecondDetailView is not working, the internal code is not available to us. But to "fix" the problem simply add .navigationViewStyle(.stack) to the NavigationView. Works for me.