1

I want to pop a NavigationLink from within code. I followed this article and it works for one link (https://swiftui-lab.com/bug-navigationlink-isactive/). However, when using a list of links, one has to use a separate boolean for each NavigationLink.

So I thought the smart way to do this is with an EnvironmentObject that holds a dictionary with a boolean for each ChildView:

class Navigation: ObservableObject{
    @Published var show:[UUID:Bool] = [:]
}

Let's say we want to have a variable number child views (of type MyObject).

What needs to be changed in order to make it work?

struct MyObject:Identifiable{
    var id = UUID()
    var name:String
}

struct ContentView: View {
    @EnvironmentObject var navigation:Navigation

    var objects = [MyObject(name: "view1"), MyObject(name: "view2"), MyObject(name: "view3")]

    init() {
        for object in objects{
            self.navigation.show[object.id] = false
        }
    }

    var body: some View {
        NavigationView{
            VStack{
                ForEach(objects, id:\.self.id){ object in
                    NavigationLink(destination: Child(object:object), isActive: self.$navigation.show[object.id], label: {
                        Text(object.name)
                    })
                }
            }
        }
    }
}

struct Child: View {
    @EnvironmentObject var navi:Navigation
    var object:MyObject

    var body: some View {
        Button(action:{self.navi.show[self.object.id] = false}, label: {
            Text("back")
        })
    }
}

1 Answer 1

6

The view that the NavigationLink navigates to has an environment variable set called presentationMode. This variable lets you programatically pop your child view back to the parent view.

So instead of having to keep track of all the display states, we can simplify your Child struct to something like this:

struct Child: View {
    @Environment(\.presentationMode) private var presentation

    var object:MyObject

    var body: some View {
        Button(action:{ self.presentation.wrappedValue.dismiss() }, label: {
            Text("back")
        })
    }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is great. Thank you!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.