swiftuiswiftui-navigationlinkios-navigationview

PresentationMode.dismiss weird behaviour when using multiple NavigationLinks inside ForEach


My app has 4 views (let's call them View_A[root] -> View_B -> View_C -> View_D). The navigation between them was made using NavigationView/NavigationLink.

When I call self.presentationMode.wrappedValue.dismiss() from the last view(View_D) I expect it to dismiss the current view (D) only, but for some reason it dismissed ALL the views and stops at view A (root view).

That's weird. I spent a couple of hours trying to figure out what's going on there and I found that - if I remove "ForEach" from "View_A" it works correctly and only the last view is dismissed. Even though ForEach gets just 1 static object in this example.

The second weird thing is that

- if I don't change "self.thisSession.stats" to false it also works correctly dismissing only the last view.

This is super weird as View_A (as far as I understand) is not dependent on thisSession environment variable.

Any ideas on how to prevent View_C and View_B from being dismissed in this case? I wanna end up at View_C after clicking the link, not at View_A.

Any help is appreciated, it took me a while to find out where it comes from but I'm not smart enough to proceed any further ;)

import SwiftUI

struct A_View: View {
    @EnvironmentObject var thisSession: CurrentSession
    
    var body: some View {
        NavigationView {
            VStack {
                Text("View A")
                ForEach([TestObject()], id: \.id) { _ in
                    NavigationLink(destination: View_B() ) {
                        Text("Move to View B")
                    }
                }
            }
        }
    }
}

struct View_B: View {
    
    var body: some View {
        NavigationView {
            NavigationLink(destination:  View_C()
            ) {
                Text("GO TO VIEW C")
            }
        }
    }
}

struct View_C: View {
    
    var body: some View {
        ZStack {
            NavigationView {
                NavigationLink(destination: View_D()) {
                    Text("GO TO VIEW D")
                }
            }
        }
    }
}

struct View_D: View {
    @EnvironmentObject var thisSession: CurrentSession
    @Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
    
    var body: some View {
        ZStack {
            VStack {
                Button(action: {
                    self.thisSession.stats = false
                    self.presentationMode.wrappedValue.dismiss()
                }) {
                    Text("Return!")
                }
            }
        }
    }
}

class CurrentSession: ObservableObject {
    @Published var stats: Bool = false
    @Published var user: String = "user"
}

struct TestObject: Identifiable, Codable {
    let id = UUID()
}

Solution

  • Your issue is with:

    NavigationView
    

    There is only supposed to be one NavigationView in an entire view stack. Try removing the NavigationView from views B and C