SwiftUI Navigation не работает должным образом с 3 представлениями, когда ссылка на третье представление встроена в кнопку панели навигации

Я начинающий разработчик Xcode/SwiftUI и застрял на следующей проблеме, связанной с навигацией. В следующем минимальном воспроизводимом примере я хочу, чтобы пользователь мог перемещаться назад по просмотру приложения после достижения ThirdView следующим образом: ThirdView -> SecondView -> FirstView (или ContentView в примере ниже).

Когда NavigationLink в SecondView для доступа к ThirdView находится в теле SecondView, все работает, как ожидалось. (Это код SecondView, который я закомментировал в приведенном ниже примере.) Однако, если я перемещаю ту же самую NavigationLink на панель навигации (как показано), нажатие кнопки панели «Вернуться ко второму представлению» в ThirdView ничего не делает. . Взгляд не меняется. Есть ли способ перемещаться из SecondView -> ThirdView с помощью ссылки навигации на кнопке панели, но при этом иметь возможность двигаться в обратном направлении из ThirdView -> SecondView?

Я прочитал несколько вопросов и ответов на подобные проблемы в Интернете, которые предполагают, что эта проблема - сбой в симуляторе Xcode, но когда я загружаю приложение на свое устройство, у меня возникает та же проблема.

      struct ContentView: View {
    @State private var activeLink: Bool = false
    var body: some View {
        NavigationView {
            VStack {
                Spacer()
                NavigationLink("Show Second Screen",
                    destination: SecondView(active: $activeLink), isActive: $activeLink)
                Spacer()
            }.padding()
            .navigationBarTitle("First view")
        }
    }
}

struct SecondView: View {
    @Binding var active: Bool
    @State private var thirdViewLink: Bool = false
    
    var body: some View {
        VStack {
        Spacer()
    // This works as expected but is not ideal for my purposes
     /* NavigationLink("Show Third View",
            destination: ThirdView(thirdViewActive: $thirdViewLink), isActive: $thirdViewLink) */
        Spacer()
        }.padding()
        .navigationBarTitle("Second View")
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: Button("Back to 1st View") {
            self.active = false
        }, trailing: NavigationLink("Show Third View",
                                    destination: ThirdView(thirdViewActive: $thirdViewLink),
                                    isActive: $thirdViewLink))
    }
}

struct ThirdView: View {
    @Binding var thirdViewActive: Bool
    var body: some View {
        VStack(spacing: 15) {
            Text("Third View")
            Spacer()
        }.padding()
        .navigationBarItems(leading: Button("Back to 2nd View") {
            self.thirdViewActive = false
        })
    }
}

1 ответ

Проблема в том, что у вас есть файл за пределами вашего.

      .navigationBarItems(leading: Button("Back to 1st View") {
    self.active = false
}, trailing: NavigationLink( /// this is not inside your NavigationView!
    "Show Third View",
    destination: ThirdView(thirdViewActive: $thirdViewLink),
    isActive: $thirdViewLink
)

Это не сработает, и вы столкнетесь со странными проблемами. NavigationLink всегда нужно быть внутри NavigationView. Вы должны следовать своему подходу, указав «Это работает, как ожидалось, но не идеально для моих целей» , и просто передать EmptyView чтобы скрыть это.

      struct SecondView: View {
    @Binding var active: Bool
    @State private var thirdViewLink: Bool = false
    
    var body: some View {
        VStack {
            Spacer()
            // This works as expected but is not ideal for my purposes
            NavigationLink(destination: ThirdView(thirdViewActive: $thirdViewLink), isActive: $thirdViewLink) {
                EmptyView()
            }
            Spacer()
        }.padding()
        .navigationBarTitle("Second View")
        .navigationBarBackButtonHidden(true)
        .navigationBarItems(leading: Button("Back to 1st View") {
            self.active = false
        }, trailing:
            Button("Show Third View") {
                self.thirdViewLink = true
            }
        )
    }
}

Другие вопросы по тегам