简体   繁体   中英

SwiftUI NavigationLink isActive Binding Not Updated/Working

I have the following:

@State private var showNext = false

...
    NavigationStack {
        VStack {
            NavigationLink(destination: NextView(showSelf: $showNext),
                           isActive: $showNext) { EmptyView() }

            Button("Show Next") {
                showNext = true
            }
        }
    }

...

struct NextView: View {
    @Binding var showSelf: Bool

    var body: some View {
        Text("Next")
         .navigationTitle("Next")

        Button("Dismiss") {
            showSelf = false
        }
            .padding(30)
    }
}

When tapping Show Next , the NextView is shown as expected.

But when tapping Dismiss , nothing happens.

Turns out that showSelf was already false before it's set to false . So it seems something went wrong with passing the binding into NextView .

What could be wrong?

The issue was caused by NavigationStack . When I replaced it with NavigationView it worked as expected.

The isActive binding of NavigationLink does not appear to work (or to be supported) when embedded in a NavigationStack .

This kind of bug happens sometimes when you haven't provided your NavigationView with a detail view correctly, eg

NavigationView {
    MainView()
    DetailView()
}

It tries to use another View further down the hierarchy that can cause things like isActive to break. In your case there is a bug in NextView that might be contributing it, you've got 2 Views but don't have a container, try changing it to this:

struct NextView: View {
    @Binding var showSelf: Bool

    var body: some View {
        HStack {
            Text("Next")
            Button("Dismiss") {
                showSelf = false
            }
        }
        .navigationTitle("Next")
    }
}

Another thing non-standard is the use of EmptyView .

You are trying to mix code for iOS >= 16 ( NavigationStack ) and for iOS < 16 (the previous way to handle NavigationLink ). Similarly for the dismiss part, which is iOS < 15.

Here is your code for iOS 16:

import SwiftUI

struct ContentView: View {
    var body: some View {
        NavigationStack {
            VStack {
                NavigationLink {
                    NextView()
                } label: {
                    Text("Show next view")
                }
            }
        }
    }
}

struct NextView: View {
    @Environment(\.dismiss) private var dismiss
    var body: some View {
        VStack {
            Text("You are in the next view")
            Button("Dismiss", action: dismiss.callAsFunction)
        }
        .navigationTitle("Next")
    }
}

I have used the simplest construction of NavigationLink . A more complex one would be used in conjunction with .navigationDestination . The best examples I have found are here:

And if you want to dive more into very strange behaviour of the stack, you can look at my post here: Found a strange behaviour of @State when combined to the new Navigation Stack - Is it a bug or am I doing it wrong?

If you need to produce code for iOS < 16, you should replace NavigationStack with NavigationView and work from there.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM