SwiftUI: NavigationDestinationLink устарел

После установки Xcode 11 beta 5 этим утром я заметил, что NavigationDestinationLink устарела в пользу NavigationLink,

Кроме того, вот что Apple говорит об этом в примечаниях к выпуску:

NavigationDestinationLink и DynamicNavigationDestinationLink устарели; их функциональность теперь включена в NavigationLink. (50630794)

Я использую NavigationDestinationLink, чтобы программно вставить новое представление в стек с помощью self.link.presented?.value = true, Эта функциональность, кажется, не присутствует в NavigationLink,

Любая идея кто-нибудь? Я бы предпочел не использовать NavigationDestinationLink больше, поскольку это устарело...

Спасибо!

ОБНОВЛЕНИЕ: На самом деле, NavigationDestinationLink способ больше не работает, так что, я думаю, у нас больше нет возможности программно использовать?

ОБНОВЛЕНИЕ 2:

NavigationLink(destination: CustomView(), isActive: $isActive) {
    return Text("")
}

Это работает, но когда вы проходите isActive в true, любое обновление состояния вызовет этот код и будет пересылать снова и снова... Кроме того, если вы передадите его обратно false, это выскакивает мнение. Не только обновления, если вы установите isActive в true, он будет толкать вид (хорошо), и если мы нажмем кнопку "Назад", он вернется назад, а затем сразу же нажмите еще раз, поскольку это все еще верно. Играть с onAppear была моя надежда, но это не называется, когда я возвращаюсь к этому... Я не уверен, как мы должны это использовать.

6 ответов

Решение

Проведя некоторое время с NavigationLink(destination:isActive) Мне нравится это намного больше, чем старый NavigationDestinationLink, Старый взгляд был немного запутанным, в то время как новый подход кажется намного более элегантным. И как только я пойму, как нажимать без анимации, это сделает восстановление состояния при запуске приложения очень простым.

Есть одна проблема, большая и ужасная ошибка.:-(

Нажатие на представление программно работает нормально, а добавление на экран программно - тоже. Проблема начинается, когда мы используем кнопку НАЗАД в толкаемом представлении, которое странно ведет себя каждый раз. В первый раз, когда представление выталкивается, оно сразу же появляется и снова выдвигается. Второй раз все работает нормально. Затем в третий раз все начинается снова.

Я создал отчет об ошибке ( номер здесь). Я рекомендую вам сделать то же самое и указать мой номер, чтобы помочь Apple сгруппировать их и привлечь больше внимания к проблеме.

Я разработал обходной путь, который в основном состоит в замене кнопки "Назад" по умолчанию нашей собственной:

class Model: ObservableObject {
    @Published var pushed = false
}

struct ContentView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        NavigationView {
            VStack {
                Button("Push") {
                    // view pushed programmatically
                    self.model.pushed = true
                }

                NavigationLink(destination: DetailView(), isActive: $model.pushed) { EmptyView() }
            }
        }
    }
}

struct DetailView: View {
    @EnvironmentObject var model: Model

    var body: some View {
        Button("Bring me Back (programatically)") {
            // view popped programmatically
            self.model.pushed = false
        }
        // workaround
        .navigationBarBackButtonHidden(true) // not needed, but just in case
        .navigationBarItems(leading: MyBackButton(label: "Back!") {
            self.model.pushed = false
        })
    }
}

struct MyBackButton: View {
    let label: String
    let closure: () -> ()

    var body: some View {
        Button(action: { self.closure() }) {
            HStack {
                Image(systemName: "chevron.left")
                Text(label)
            }
        }
    }
}

Чтобы улучшить обходной путь без замены кнопки "Назад" на пользовательскую, используйте приведенный выше код:

NavigationLink(destination: Test().onAppear(perform: {
    self.editPushed = nil
}), tag: 1, selection: self.$editPushed) {
    Button(action: {
        self.editPushed = 1
    }) {
        Image(systemName: "plus.app.fill")
            .font(.title)
    }
}

Блок onAppear сотрет значение выбора, предотвращая двойное отображение подробного вида.

Вы также можете использовать NavigationLink(назначение: тег: выбор)

NavigationLink(destination: MyModal(), tag: 1, selection: $tag) {
    EmptyView()
}

Таким образом, программно вы можете установить тэг на 1, чтобы нажать MyModal. Этот подход работает так же, как и в случае с переменной связывания Bool, поэтому, когда вы открываете первый раз, он сразу же отображает представление, надеюсь, они исправят это в следующей бета-версии.

Единственный недостаток этого подхода по сравнению с DynamicNavigationDestinationLink заключается в том, что вам нужно предоставить View to NavigationLink, даже если он вам не нужен. Надеемся, что они найдут более чистый способ, позволяющий нам продвигаться программно.

Метод, использованный в выбранном ответе, снова устарел. Вот решение, скопированное из этого ответа в этом посте .

          @State private var readyToNavigate : Bool = false

    var body: some View {
        NavigationStack {
           VStack {
              Button {
                  //Code here before changing the bool value
                  readyToNavigate = true
              } label: {
                  Text("Navigate Button")
              }
          }
           .navigationTitle("Navigation")
           .navigationDestination(isPresented: $readyToNavigate) {
              MyTargetView()
          }
       }
   }

Нашел здесь ответ NavigationLink.

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

.navigationBarItems(leading:
                Button(action: {
                    self.showDetail = false
                }) {
                    Image(systemName: "chevron.left").foregroundColor(.red)
                        .font(.system(size: 24, weight: .semibold))
                    Text("Back").foregroundColor(.red)
                    .font(.system(size: 19))
                }
            )
Другие вопросы по тегам