Search code examples
iosswiftswiftuiswiftui-navigationlink

Can't pop current screen in SwiftUI using NavigationView and NavigationLink


So I have a problem regarding NavigationView and NavigationLinks in SwiftUI while trying to pop the current screen, which is not working in this case.

I have 3 Screens A -> B -> C

Each screen has a button for popping itself.

The pop from B -> A works, but when you navigate from A -> B -> C, the pop from C -> B it's not working.

Do you know what would be the problem? I will attach the code below and a video. The app should support iOS 14.

enter image description here

struct ScreenA: View {
    @State private var showB = false
    
    var body: some View {
        NavigationView {
            VStack {
                Button("Go to B") {
                    showB = true
                }
                
                NavigationLink(destination: ScreenB(didTapGoBack: {
                    showB = false
                }), isActive: $showB) {
                    EmptyView()
                }
            }
        }
    }
}
struct ScreenB: View {
    var didTapGoBack: () -> Void
    @State var showC = false

    var body: some View {
        VStack {
            Button("Go to C") {
                showC = true
            }
        
            Button("Back to Screen A") {
                didTapGoBack()
            }
            
            NavigationLink(destination: ScreenC(didTapGoBack: {
                showC = false
            }), isActive: $showC) {
                EmptyView()
            }
        }
    }
}
struct ScreenC: View {
    var didTapGoBack: () -> Void
    
    var body: some View {
        VStack {
            Text("Screen C")
            Button("Back to Screen B") {
                didTapGoBack()
            }
        }
    }
}
@main
struct TestNavApp: App {
    var body: some Scene {
        WindowGroup {
            ScreenA()
        }
    }
}

Solution

  • So a solution for this would be adding .isDetailLink(false) on the first NavigationLink, maybe the NavigationView by default works a Split navigation like master-detail, so maybe thats why the first pop was working, but by adding this you are telling the NavigationView to work as a stack.

    Now the navigation works as expected A -> B -> C:

    struct ScreenA: View {
        @State private var showB = false
        
        var body: some View {
            NavigationView {
                VStack {
                    Button("Go to B") {
                        showB = true
                    }
                    
                    NavigationLink(destination: ScreenB(didTapGoBack: {
                        showB = false
                    }), isActive: $showB) {
                        EmptyView()
                    }.isDetailLink(false)
                }
            }
        }
    }