NavigationLink zawiesza się podczas próby powrotu do poprzednio klikniętego NavigationLink w SwiftUI

10

Projektuję aplikację, która zawiera funkcję pobierania danych JSON i wyświetlania listy pobranych elementów w widoku typu FileBrowser. W tym widoku użytkownik powinien mieć możliwość kliknięcia folderu w celu głębszego zanurzenia się w drzewie plików lub kliknięcia pliku, aby wyświetlić metadane dotyczące tego pliku.

Zauważyłem, że kiedy to działa, kiedy klikam plik lub folder, a następnie wracam i klikam go ponownie, NavigationLink nie jest wyzwalany i utknąłem na widoku, dopóki nie kliknę w inny NavigationLink.

Oto gif demonstrujący ten problem.

Błąd podwójnego dotknięcia

Jak widać tutaj, kiedy klikam BlahBlah, aktywuję NavigationLink i zabieram się do BlahBlah, a następnie, gdy nawiguję z powrotem i próbuję ponownie nawigować do BlahBlah, robi się szary, rejestrując, że kliknąłem na niego ... ale nigdy mnie tam nie przenosi . Kliknięcie TestFile naprawia to i pozwala mi wrócić do BlahBlah.

Elementy listy są tworzone za pomocą następujących struktur

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

i wywoływane w widoku z NavigationLinks w następujący sposób

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

Mój widok nawigacji jest inicjowany w powyższym widoku (aplikacja ma widok zakładki) w następujący sposób

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 to struktura, której używam do obsługi koloru paska nawigacji. Jest tak skonfigurowane

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

}

Nie sądzę, że mój konfigurator nawigacji powoduje to? Ten błąd występuje również w innych linkach do nawigacji w aplikacji, ale najłatwiej było go zademonstrować tutaj w widoku FileBrowser.

To może być błąd w SwiftUI? Jeśli tak, to czy ktoś zna sposób na obejście tego? Jeśli nie, co robię źle?

Vapidant
źródło
Nie jestem do końca pewien. Ale nie należy owinąć NavigationLinkWewnątrz NavigationViewi usunąć NavigationViewz FileView? Widziałem kilka przykładów, które robią to w ten sposób.
Giovanni,
@ GiovanniTerlingen O ile nie rozumiem, co mówisz, to właśnie robię. To, co NavigationLinkjest w środku, FileViewjest owinięte, NavigationViewdlatego NavigationLinkjest owinięte wNavigationView
Vapidant
Podaj minimalny możliwy do uruchomienia projekt. Nie mogę tego odtworzyć, więc prawdopodobnie nie jest to jeden z błędów SwiftUI.
Mojtaba Hosseini
czy możesz podać pełny kod źródłowy, abym mógł rozwiązać Twój problem
Hardik Bar
jak się przygotować cellArray?
E.Coms,

Odpowiedzi:

5

Miał ten sam problem - spróbuj tego. Nazwałbym to hackem, który należy usunąć, gdy błąd w swiftUI zostanie naprawiony.

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)

Zasadniczo wydaje się, że w niektórych okolicznościach (iOS 13.3 - symulator?) NavigationLink nie jest resetowany po usunięciu widoku docelowego ze stosu nawigacji. Aby obejść ten problem, musimy ponownie wygenerować łącze nawigacyjne. To właśnie zmienia identyfikator. To rozwiązało mój problem.

Jeśli jednak masz Nawiązane łącza Nawigacyjne, czyli link prowadzący do innej listy łączy, wówczas to rozwiązanie spowoduje skutki uboczne; stos powraca do początku przy drugiej próbie wyświetlenia ostatniego widoku.

VJK
źródło
Ten błąd został naprawiony w najnowszej wersji IOS. Zaznaczam to jako poprawną odpowiedź z powodu rozwiązania problemu w obecnej formie, jednak nie powinno to stanowić problemu. Podoba mi się również twoje wyjaśnienie problemu. Dziękuję Ci.
Vapidant,
Kiedy mówisz o najnowszej wersji iOS, masz na myśli 13.4 czy wersję beta?
Ricardo Alves,
Też chciałbym wiedzieć. Która wersja działa poprawnie? Mam 13.3 (który jest teraz najnowszym iOS) i problem nadal występuje.
Mallow
Uważam, że ten błąd został zaprezentowany w wersji beta IOS 13.3, ale został naprawiony w wersji IOS 13.3 Beta 4.
Vapidant