BlowMyMind
BlowMyMind

Reputation: 673

Non-deprecated way to call NavigationLink on Buttons

This is the old way of calling NavigationLink on Buttons

struct ContentView: View {
    @State private var selection: String? = nil
    var body: some View {
        NavigationView {
            VStack {
                NavigationLink(destination: View1(), tag: "tag1", selection: $selection) {
                    EmptyView()
                }
                NavigationLink(destination: NotView1(), tag: "tag2", selection: $selection) {
                    EmptyView()
                }

                Button("Do work then go to View1") {
                    // do some work that takes about 1 second
                    mySleepFunctionToSleepOneSecond()
                    selection = "tag1"
                }

                Button("Instantly go to NotView1") {
                    selection = "tag2"
                }
            }
            .navigationTitle("Navigation")

        }
    }
}

This code works perfectly. It can go to different View targets depending on which button is clicked. Not only that, it guarantees all work is done BEFORE navigating to the target view. However, the only issue is that 'init(destination:tag:selection:label:)' was deprecated in iOS 16.0: use NavigationLink(value:label:) inside a List within a NavigationStack or NavigationSplitView

I get NavigationStack is awesome and such. But how can I translate the code to use the new NavigationStack + NavigationLink. Especially, how can I make sure work is done Before navigation?

Upvotes: 3

Views: 1966

Answers (2)

Evgeny K
Evgeny K

Reputation: 3187

Using new NavigationStack and its path property you can do much more. Your example will be transformed to

struct ContentView: View {
    @State private var path = [String]()
    var body: some View {
        NavigationStack(path: $path) {
            VStack {
                Button("Do work then go to View1") {
                    // do some work that takes about 1 second
                    mySleepFunctionToSleepOneSecond()
                    path.append("tag1")
                }

                Button("Instantly go to NotView1") {
                    path.append("tag2")
                }
            }
            .navigationTitle("Navigation")
            .navigationDestination(for: String.self) { route in
                switch route {
                case "tag1":
                    EmptyView()
                case "tag2":
                    EmptyView()
                default:
                    EmptyView()
                }
            }
        }
    }
}

Check this video. There you can find more use cases.

Upvotes: 2

Namra Parmar
Namra Parmar

Reputation: 255

For using non deprecated and after doing some work if we want to go to next view or in anyview there is something called ".navigationDestination". Let's see that using simple example.

    @State var bool : Bool = false

    var body: some View {
        NavigationStack {
           VStack {
              Text("Hello, world!")
            
              Button {
              //Code here before changing the bool value
                  bool = true
              } label: {
                  Text("Navigate Button")
              }
          }.navigationDestination(isPresented: $bool) {
              SwiftUIView()
          }
       }
   }

In this code we change take bool value as false and change it to true when our work is done using button.

.navigationDestination(isPresented: Binding<Bool>, destination: () -> View)

In .navigationDestination pass the Binding bool and provide the view you want to navigate.

You can use .navigationDestination multiple times.

Hope you found this useful.

Upvotes: 2

Related Questions