O NavigationLink congela ao tentar revisitar o NavigationLink anteriormente clicado no SwiftUI

10

Estou projetando um aplicativo que inclui a função de recuperar dados JSON e exibir uma lista de itens recuperados em uma exibição do tipo FileBrowser. Nessa visão, um usuário deve poder clicar em uma pasta para mergulhar mais fundo na árvore de arquivos ou clicar em um arquivo para visualizar alguns metadados sobre o referido arquivo.

Observei que, enquanto isso está funcionando, quando clico em um arquivo ou pasta e depois clico nele novamente, o NavigationLink não é acionado e fico preso na visualização até clicar em outro NavigationLink.

Aqui está um gif demonstrando esse problema.

Erro de toque duplo

Como visto aqui, quando clico em BlahBlah, estou ativando o NavigationLink e levado para BlahBlah; quando navego de volta e tento renavegar para BlahBlah, ele fica cinza, registrando que eu clicava nele ... mas nunca me transporta para lá . Clicar em TestFile corrige isso e permite navegar de volta para BlahBlah.

Os itens da lista são feitos com as seguintes estruturas

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)
                }
        }
    }
}

e visualizado com navigationLinks da seguinte maneira

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)
                    }
                }
            }

Meu NavigationView é inicializado na visualização acima (o aplicativo tem uma visualização de guia), da seguinte maneira

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)
}

O NavigationConfigurator é uma estrutura que eu uso para manipular a cor da navigationBar. Está configurado assim

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)
        }
    }

}

Não acho que meu NavigationConfigurator esteja causando isso? Esse bug também ocorre em outros links de navegação no aplicativo, mas foi mais fácil demonstrá-lo aqui na visualização FileBrowser.

Isso pode ser um bug no SwiftUI? Se é que alguém sabe uma maneira de contornar isso? Se não for, o que estou fazendo de errado?

Vapidant
fonte
Eu não tenho tanta certeza. Mas você não deve envolver NavigationLinkdentro de um NavigationViewe remover NavigationViewdo FileView? Eu vi alguns exemplos por aqui que fazem dessa maneira.
Giovanni
@GiovanniTerlingen A menos que eu esteja entendendo mal o que você está dizendo, é isso que estou fazendo. O NavigationLinkinterior FileViewé envolto em um, NavigationViewportanto, NavigationLinké envolto dentro de umNavigationView
Vapidant
Forneça um projeto executável mínimo. Não consigo reproduzir isso, então provavelmente não é um dos erros do SwiftUI.
Mojtaba Hosseini
você pode fornecer o código fonte completo para que eu possa resolver o seu problema
Hardik Bar
como você se preparou cellArray?
E.Coms

Respostas:

5

Teve o mesmo problema - tente isso. Eu chamaria isso de hack para ser removido quando o bug no swiftUI for corrigido.

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)

Essencialmente, parece que em algumas circunstâncias (iOS 13.3 - Simulator?) O NavigationLink não é redefinido quando a visualização de destino é removida da pilha de navegação. Como solução, precisamos regenerar o link de navegação. É isso que altera o id. Isso corrigiu meu problema.

No entanto, se você tiver NavigationLinks encadeados, ou seja, um link que leva a outra lista de links, essa solução criará efeitos colaterais; a pilha retorna à origem na segunda tentativa de mostrar a última visualização.

VJK
fonte
Este bug foi corrigido na versão mais recente do IOS. Estou marcando isso como a resposta correta por resolver o problema como estava, no entanto, isso não deve ser um problema. Também gosto da sua explicação do problema. Obrigado.
Vapidant
Quando você diz a versão mais recente do iOS, quer dizer 13.4 ou uma versão beta?
Ricardo Alves
Eu gostaria de saber também. Qual versão funciona correta? Tenho 13.3 (que é o iOS mais recente no momento) e o problema ainda está lá.
mallow
Eu acredito que este bug foi apresentado em uma IOS 13.3 Beta Build mas foi corrigido a partir de IOS 13.3 Beta 4.
Vapidant