0

I'm experiencing a quite strange behavior from the NavigationLink.

When I'm setting the selection of the NavigationLink from outside the list to nil the view pops back. If I do the same thing from inside the list it's not working. Even when I'm in the child view and am setting it to the variable from outside the list and then to nil it works. It seems like that the child view is somehow forgetting about the NavigationLink within the list.

Solutions like this (NavigationLink tag and selection not working as expected) with the @Environment(\.presentationMode) are not working in the custom NavigationBar or at least I don't know how.

What am I missing here? Any help is much appreciated :)

App entry:

struct MainView : View {
    @ObservedObject var dbhandler = DBhandler()
    var body: some View {
        VStack{
            Header()
                .frame(height: 50)
            
            NavigationDummy()
        }.environmentObject(dbhandler)
    }
}

Environmental object for navigation and model:

class DBhandler: ObservableObject {
    @Published var navSelection : String? = nil
}

struct DummyObject {
    var year: Int
    var names: [String]
}

Custom NavigationBar:

struct Header: View{
    @EnvironmentObject var dbhandler: DBhandler
    var body: some View{
        HStack{
            Button {
                dbhandler.navSelection = nil
            } label: {
                Text("Back")
            }
            Text("Current view: \(dbhandler.navSelection ?? "Empty")")
        }
    }
}

Parent View:

struct NavigationDummy: View {
    @EnvironmentObject var dbhandler: DBhandler
    var dummyList : [DummyObject] = [DummyObject(year: 2020, names: ["Jo", "Alex"]), DummyObject(year: 2019, names: ["Mike", "Nancy"])]
    
    var body: some View {
        NavigationView{
            VStack{
                List{
                    ForEach(dummyList, id:\.year){ object in
                        Section(header: Text(String(object.year))){
                            ForEach(object.names, id:\.self) {name in
                                Button {
                                    dbhandler.navSelection = name
                                } label: {
                                    VStack{
                                        Text(name)
                                        NavigationLink(destination: ChildView(), tag: name, selection: $dbhandler.navSelection) {
                                            EmptyView()
                                        }.hidden()
                                    }
                                }
                            }
                        }
                    }
                }
                
                NavigationLink(destination: ChildView(), tag: "OutsideList", selection: $dbhandler.navSelection) {
                    EmptyView()
                }
                
                Button {
                    dbhandler.navSelection = "OutsideList"
                } label: {
                    Text("Detail view from outside list")
                }

            }
        }
    }
}

ChildView:

struct ChildView: View {
    @EnvironmentObject var dbhandler: DBhandler
    
    var body: some View {
        VStack{
            
            Button {
                dbhandler.navSelection = "OutsideList"
            } label: {
                Text("Outside list")
            }
            
            Button {
                dbhandler.navSelection = "Jo"
            } label: {
                Text("Inside list")
            }
        }.navigationBarHidden(true)
    }
}
FriendlyGuy
  • 331
  • 5
  • 14

1 Answers1

1

The current workaround I use is to have a placeholder root NavigationLink in the Parent View like this:

NavigationLink(destination: EmptyView(), tag: "Root", 
               selection: self.$dbhandler.navSelection,
               label: {
               EmptyView()
               }).hidden()

and then in the header do this to pop back:

    dbhandler.navSelection = "Root"
    
    DispatchQueue.main.asyncAfter(deadline: .now() + 0.01) {
        dbhandler.navSelection = nil
    }

But that's not the ideal way ...

FriendlyGuy
  • 331
  • 5
  • 14