Контроллер навигации SwiftUI заикается с двумя навигационными ссылками на строку списка

Я пытаюсь создать две ссылки NavigationLink в повторяющемся списке. У каждого свое предназначение. Весь код работает нормально, пока я не вставил вызов корневого представления в цикл List/ForEach. В этот момент навигация становится очень странной.

Попробуйте щелкнуть любую ссылку, а затем щелкните индикатор возврата вверху. Он перейдет на одну ссылку NavigationLink, а затем на другую. Иногда в другом порядке, а иногда он автоматически возвращается по одной из ссылок, а иногда не открывает второе подробное представление, пока вы не вернетесь из первого подробного представления. Это происходит как в режиме предварительного просмотра, так и при сборке и запуске приложения.

Я сократил код до самого простого, приведенного ниже. Если вы прокомментируете 2 строки, как указано в ContentView, вы увидите правильное поведение.

Я использую Catalina 10.15.5, xCode 11.6 с целевым приложением iOS 13.6.

Как я могу изменить код, чтобы он работал с циклом List/ForEach?

import SwiftUI

struct DetailView1: View {
    var body: some View {
        HStack {
            Text("Here is Detail View 1." )}
            .foregroundColor(.green)
    }
}

struct DetailView2: View {
    var body: some View {
        HStack {
            Text( "Here is Detail View 2.") }
            .foregroundColor(.red)
    }
}

struct RootView: View {
    var body: some View {
        HStack {
            VStack {
                NavigationLink(destination: DetailView1())
                { VStack { Image(systemName: "ant.circle").resizable()
                    .frame(width:75, height:75)
                    .scaledToFit()
                }.buttonStyle(PlainButtonStyle())
                    Text("Tap for Detail 1.")
                        .foregroundColor(.green)
                }
            }
            NavigationLink(destination: DetailView2())
            { Text("Tap for Detail 2.")
                .foregroundColor(.red)
            }
        }
    }
}

struct ContentView: View {
    var body: some View {
        NavigationView {
            // Comment the following line for correct behavior
            List { ForEach(0..<3) {_ in
                RootView()
                // Comment the following line for correct behavior
                }  }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        NavigationView {
            ContentView()
                .navigationBarTitle("Strange Behavior")
        }
    }
}

1 ответ

Решение

В вашем случае обе навигационные ссылки активируются сразу, пользователь нажимает строку, чтобы избежать этого, ниже возможен подход

Протестировано с Xcode 12 / iOS 14

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

struct RootView: View {
    @State private var isFirst = false
    @State private var isActive = false
    var body: some View {
        HStack {
            VStack {
                Button(action: {
                    self.isFirst = true
                    self.isActive = true
                })
                { VStack { Image(systemName: "ant.circle").resizable()
                    .frame(width:75, height:75)
                    .scaledToFit()
                }
                    Text("Tap for Detail 1.")
                        .foregroundColor(.green)
                }
            }
            Button(action: {
                self.isFirst = false
                self.isActive = true
            })
            { Text("Tap for Detail 2.")
                .foregroundColor(.red)
            }
            .background(
                NavigationLink(destination: self.destination(), isActive: $isActive) { EmptyView() }
            )
        }
        .buttonStyle(PlainButtonStyle())
    }

    @ViewBuilder
    private func destination() -> some View {
        if isFirst {
            DetailView1()
        } else {
            DetailView2()
        }
    }
}
Другие вопросы по тегам