NavigationLink замикається при спробі переглянути раніше натиснуту кнопку NavigationLink у SwiftUI


10

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

Я помічав, що, коли це працює, коли я клацаю на файл або папку, а потім повертаюся назад і натискаю на неї знову, NavigationLink не спрацьовує, і я застряг у перегляді, поки не натисну інший NavigationLink.

Ось подарунок, який демонструє цю проблему.

Помилка подвійного торкання

Як бачимо тут, коли я натискаю на 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)
                }
        }
    }
}

і переглядаються за допомогою навігаційних посилань наступним чином

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? Якщо це хтось знає спосіб подолати це? Якщо це не так, що я роблю неправильно?


Я не дуже впевнений. Але ви не повинні загорнути NavigationLinkвсередину NavigationViewта видалити NavigationViewз FileView? Я бачив кілька прикладів, які роблять це саме так.
— Джованні

@GiovanniTerlingen Якщо я не розумію, що ти говориш, це я і роблю. NavigationLinkЗнаходиться всередині FileViewякого обгорнутий в NavigationViewтому NavigationLinkобгорнутий внутрішню частинуNavigationView
— Vapidant

Будь ласка, надайте мінімальний проект, який можна виконати. Я не можу це відтворити, тому, ймовірно, це не одна з помилок SwiftUI.
— Mojtaba

чи можете ви надати повний вихідний код, щоб я міг вирішити вашу проблему
— Hardik Bar

як ти готувався 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 не скидається, коли вигляд пункту призначення видаляється з навігаційного стеку. Для вирішення проблеми нам потрібно відновити Навігаційне посилання. Ось що робить зміна ідентифікатора. Це виправило мою проблему.

Однак якщо у вас є навігаційні посилання, пов'язані ланцюгом, тобто посилання, що веде до іншого списку посилань, то це рішення створить побічні ефекти; стек повертається до початкового коду при другій спробі показати останній вигляд.


Ця помилка виправлена ​​в останній версії IOS. Я відзначаю це правильною відповіддю, оскільки вирішував питання, як воно стояло, однак це не повинно бути проблемою. Мені також подобається ваше пояснення проблеми. Дякую.
— Вапідант

Коли ви говорите останню версію iOS, ви маєте на увазі 13.4 чи бета-версію?
— Рікардо Алвеш

Я також хотів би це знати. Яка версія працює правильно? У мене 13,3 (що є останнім iOS зараз), і проблема все ще є.
— мальва

Я вважаю, що ця помилка була представлена ​​в бета-версії IOS 13.3, але її було виправлено станом на IOS 13.3 Beta 4.
— Vapidant
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.