NavigationLink se bloque lorsque vous essayez de revoir NavigationLink cliqué précédemment dans SwiftUI

10

Je conçois une application qui inclut la fonction de récupération des données JSON et d'affichage d'une liste des éléments récupérés dans une vue de type FileBrowser. Dans cette vue, un utilisateur doit pouvoir cliquer sur un dossier pour plonger plus profondément dans l'arborescence de fichiers ou cliquer sur un fichier pour afficher des métadonnées sur ledit fichier.

J'ai observé que pendant que cela fonctionne, lorsque je clique sur un fichier ou un dossier, puis que je reviens en arrière et que je clique à nouveau dessus, le NavigationLink n'est pas déclenché et je suis bloqué sur la vue jusqu'à ce que je clique sur un autre NavigationLink.

Voici un gif illustrant ce problème.

Bug Double Tap

Comme on le voit ici, lorsque je clique sur BlahBlah, j'active le NavigationLink et je suis amené à BlahBlah, puis quand je reviens en arrière et essaye de renaviguer vers BlahBlah, il devient gris, enregistrant que j'ai cliqué dessus ... mais ne m'y transporte jamais . Cliquer sur TestFile corrige cela et me permet de revenir à BlahBlah.

Les éléments de la liste sont créés avec les structures suivantes

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

et appelé en vue avec navigationLinks comme suit

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

Mon NavigationView est initialisé dans la vue ci-dessus (l'application a une vue d'onglet) comme suit

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

Le NavigationConfigurator est une structure que j'utilise pour gérer la couleur de la barre de navigation. Il est configuré comme ça

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

}

Je ne pense pas que ma NavigationConfigurator soit à l'origine de cela? Ce bogue se produit également dans d'autres liens de navigation de l'application, mais il était plus facile de le démontrer ici dans la vue FileBrowser.

Cela pourrait être un bug dans SwiftUI? Si c'est le cas, quelqu'un connaît-il un moyen de contourner ce problème? Si ce n'est pas le cas, que fais-je de mal?

Vapidant
la source
Je ne suis pas vraiment sûr. Mais ne devriez-vous pas envelopper l' NavigationLinkintérieur NavigationViewet le retirer NavigationViewdu FileView? J'ai vu quelques exemples ici qui le font de cette façon.
Giovanni
@GiovanniTerlingen À moins que je ne comprenne mal ce que vous dites, c'est ce que je fais. L' NavigationLinkest à l'intérieur de FileViewqui est enveloppé dans un NavigationViewdonc l' NavigationLinkest à l'intérieur d'unNavigationView
Vapidant
Veuillez fournir un projet exécutable minimum. Je ne peux pas reproduire cela, donc ce n'est probablement pas un des bugs de SwiftUI.
Mojtaba Hosseini
pouvez-vous fournir le code source complet pour que je puisse résoudre votre problème
Hardik Bar
comment vous êtes-vous préparé cellArray?
E.Coms

Réponses:

5

Eu le même problème - essayez ceci. J'appellerais cela un hack à supprimer lorsque le bogue dans swiftUI est corrigé.

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)

Essentiellement, il semble que dans certaines circonstances (iOS 13.3 - Simulator?) Le NavigationLink n'est pas réinitialisé lorsque la vue de destination est supprimée de la pile de navigation. En guise de solution, nous devons régénérer le lien de navigation. C'est ce que fait le changement d'identifiant. Cela a corrigé mon problème.

Cependant, si vous avez des liens de navigation chaînés, c'est-à-dire un lien menant à une autre liste de liens, cette solution créera des effets secondaires; la pile revient à l'origine à la deuxième tentative pour afficher la dernière vue.

VJK
la source
Ce bug est corrigé dans la dernière version d'IOS. Je marque cela comme la bonne réponse en raison de la résolution du problème tel qu'il est, cependant, cela ne devrait pas être un problème. J'aime aussi votre explication du problème. Je vous remercie.
Vapidant
Quand vous dites dernière version iOS, vous voulez dire 13.4 ou une version bêta?
Ricardo Alves
J'aimerais aussi savoir. Quelle version fonctionne correctement? J'ai 13,3 (qui est le dernier iOS en ce moment) et le problème est toujours là.
mauve
Je crois que ce bogue a été présenté dans une version bêta d'IOS 13.3 mais a été corrigé à partir d'IOS 13.3 Bêta 4.
Vapidant