NavigationLink зависает при попытке вернуться к ранее нажатой NavigationLink в SwiftUI

10

Я разрабатываю приложение, которое включает функцию извлечения данных JSON и отображения списка извлеченных элементов в представлении типа FileBrowser. В этом представлении пользователь должен иметь возможность щелкнуть папку, чтобы углубиться в дерево файлов, или щелкнуть файл, чтобы просмотреть некоторые метаданные об указанном файле.

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

Вот gif, демонстрирующий эту проблему.

Ошибка двойного нажатия

Как видно здесь, когда я нажимаю на BlahBlah, я активирую NavigationLink и перехожу на BlahBlah, затем, когда я возвращаюсь назад и пытаюсь вернуться к BlahBlah, он становится серым, регистрируя, что я нажал на него ... но затем никогда не переносит меня туда , Нажатие на TestFile исправляет это и позволяет мне вернуться к BlahBlah.

Элементы списка сделаны со следующими структурами

private struct FileCell{
    var FileName: String
    var FileType: String
    var FileID: String = ""
    var isContainer: Bool
}

private struct constructedCell: View{

    var FileType: String
    var FileName: String
    var FileID: String

    var body: some View {
        return
            HStack{
                VStack(alignment: .center){
                    Image(systemName: getImage(FileType: FileType)).font(.title).frame(width: 50)
                }
                Divider()
                VStack(alignment: .leading){
                    Text(FileName).font(.headline)
                        .multilineTextAlignment(.leading)
                    Text(FileID)
                        .font(.caption)
                        .multilineTextAlignment(.leading)
                }
        }
    }
}

и вызывается с помощью navigationLinks следующим образом

List(cellArray, id: \.FileID) { cell in
                if (cell.isContainer) {
                    NavigationLink(destination: FileView(path: "/\(cell.FileID)", displaysLogin: self.$displaysLogin).navigationBarTitle(cell.FileName)){
                        constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID)
                    }
                } else {
                    NavigationLink(destination: DetailView(FileID: cell.FileID).navigationBarTitle(cell.FileName)){
                        constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID)
                    }
                }
            }

Мой NavigationView инициализируется в представлении выше (приложение имеет вид вкладки) это следующим образом

TabView(selection: $selection){
               NavigationView{
                    FileView(displaysLogin: self.$displaysLogin)
                        .navigationBarTitle("Home", displayMode: .inline)
                        .background(NavigationConfigurator { nc in
                            nc.navigationBar.barTintColor = UIColor.white
                            nc.navigationBar.titleTextAttributes = [.foregroundColor : UIColor.black]
                        })
                }
                .font(.title)
                .tabItem {
                    VStack {
                        Image(systemName: "folder.fill")
                        Text("Files")
                    }
                }
                .tag(0)
}

NavigationConfigurator - это структура, которую я использую для обработки цвета панели навигации. Это настроено так

struct NavigationConfigurator: UIViewControllerRepresentable {
    var configure: (UINavigationController) -> Void = { _ in }

    func makeUIViewController(context: UIViewControllerRepresentableContext<NavigationConfigurator>) -> UIViewController {
        UIViewController()
    }
    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<NavigationConfigurator>) {
        if let nc = uiViewController.navigationController {
            self.configure(nc)
        }
    }

}

Я не думаю, что мой NavigationConfigurator вызывает это? Эта ошибка также возникает в других навигационных ссылках в приложении, но ее было проще всего продемонстрировать здесь в представлении FileBrowser.

Это может быть ошибка в SwiftUI? Если это кто-нибудь знает способ обойти это? Если это не так, что я делаю не так?

Vapidant
источник
Я не совсем уверен. Но не следует ли вам завернуть NavigationLinkвнутрь NavigationViewи удалить NavigationViewиз FileView? Я видел несколько примеров здесь, которые делают это таким образом.
Джованни
@GiovanniTerlingen Если я не понимаю, что вы говорите, это то, что я делаю. NavigationLinkНаходится внутри FileViewкоторого обернут в NavigationViewпоэтому NavigationLinkобернут внутреннюю частьNavigationView
Vapidant
Пожалуйста, предоставьте минимальный работоспособный проект. Я не могу воспроизвести это, так что, вероятно, это не одна из ошибок SwiftUI.
Мойтаба Хоссейни
Можете
как ты готовился cellArray?
E.Coms

Ответы:

5

Была такая же проблема - попробуйте это. Я бы назвал это хаком, который будет удален, когда ошибка в swiftUI исправлена.

struct ListView: View {
@State private var destID = 0
...
var body: some View {
...
  NavigationLink(destination: FileView(path: "/\(cell.FileID)", displaysLogin: self.$displaysLogin)
   .navigationBarTitle(cell.FileName) 
   .onDisappear() { self.destID = self.destID + 1 }
  ){
   constructedCell(FileType: cell.FileType, FileName: cell.FileName, FileID: cell.FileID) 
  }.id(destID)

По сути, кажется, что в некоторых обстоятельствах (iOS 13.3 - Симулятор?) NavigationLink не сбрасывается, когда вид назначения удаляется из стека навигации. В качестве обходного пути нам нужно восстановить навигационную ссылку. Это то, что делает изменение идентификатора. Это исправило мою проблему.

Однако, если у вас есть NavigationLink, которые связаны между собой, то есть ссылка, которая ведет к другому списку ссылок, тогда это решение создаст побочные эффекты; стек возвращается к источнику при второй попытке показать последнее представление.

Vjk
источник
Эта ошибка исправлена ​​в последней версии IOS. Я отмечаю это как правильный ответ из-за решения проблемы в ее нынешнем виде, однако это не должно быть проблемой. Мне также нравится ваше объяснение проблемы. Спасибо.
Vapidant
Когда вы говорите последнюю версию iOS, вы имеете в виду 13.4 или бета-версию?
Рикардо Алвес
Я тоже хотел бы знать. Какая версия работает правильно? У меня 13,3 (это последняя версия iOS), и проблема все еще существует.
мальва
Я считаю, что эта ошибка была представлена ​​в бета-сборке IOS 13.3, но была исправлена ​​в IOS 13.3 Beta 4.
Vapidant