简体   繁体   English

尝试在 SwiftUI 中重新访问之前单击的 NavigationLink 时,NavigationLink 冻结

[英]NavigationLink freezes when trying to revisit previously clicked NavigationLink in SwiftUI

I am designing an app that includes the function of retrieving JSON data and displaying a list of retrieved items in a FileBrowser type view.我正在设计一个应用程序,其中包括检索 JSON 数据和在 FileBrowser 类型视图中显示检索项目列表的功能。 In this view, a user should be able to click on a folder to dive deeper into the file tree or click on a file to view some metadata about said file.在此视图中,用户应该能够单击文件夹以深入了解文件树或单击文件以查看有关该文件的一些元数据。

I've observed that while this is working, when I click on a file or folder then go back and click on it again, the NavigationLink is not triggered and I am stuck on the view until I click into a different NavigationLink.我观察到,在此过程中,当我单击一个文件或文件夹然后返回并再次单击它时,不会触发 NavigationLink,并且在单击不同的 NavigationLink 之前我一直停留在视图上。

Here is a gif demonstrating this problem.这是演示此问题的 gif。

双击错误

As seen here, when I click on BlahBlah I am activating the NavigationLink and taken to BlahBlah, then when I navigate back and try to renavigate to BlahBlah, it becomes grey, registering that I clicked on it... but then never transports me there.如图所示,当我点击 BlahBlah 时,我激活了 NavigationLink 并被带到了 BlahBlah,然后当我返回并尝试重新导航到 BlahBlah 时,它变成灰色,表明我点击了它...... . Clicking on TestFile fixes this and allows me to navigate back to BlahBlah.单击 TestFile 修复了这个问题,并允许我导航回 BlahBlah。

The list items are made with the following structs列表项由以下结构组成

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

and called into view with navigationLinks as follows并使用导航链接调用视图如下

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

My NavigationView is initialized in the view above (the app has a tab view) this as follows我的 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)
}

The NavigationConfigurator is a struct I use for handling the color of the navigationBar. NavigationConfigurator 是我用来处理导航栏颜色的结构。 It is set up like so它是这样设置的

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

}

I do not think my NavigationConfigurator is causing this?我不认为我的 NavigationConfigurator 导致了这个? This bug also happens in other navigationLinks in the app, but it was easiest to demonstrate it here in the FileBrowser view.这个错误也发生在应用程序的其他导航链接中,但最容易在 FileBrowser 视图中演示它。

This might be a bug in SwiftUI?这可能是 SwiftUI 中的一个错误? If it is does anyone know a way to work around this?如果是的话,有人知道解决这个问题的方法吗? If it isn't, what am I doing wrong?如果不是,我做错了什么?

Had the same issue - try this.有同样的问题 - 试试这个。 I would call this a hack to be removed when the bug in swiftUI is corrected.当 swiftUI 中的错误得到纠正时,我会将其称为要删除的 hack。

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)

Essentially it seems that in some circumstances (iOS 13.3 - Simulator?) the NavigationLink is not reset when the destination view is removed from the navigation stack.从本质上讲,在某些情况下(iOS 13.3 - 模拟器?),当目标视图从导航堆栈中删除时,NavigationLink 不会重置。 As a work around we need to regenerate the Navigation Link.作为一种解决方法,我们需要重新生成导航链接。 This is what changing the id does.这就是更改 id 的作用。 This corrected my issue.这纠正了我的问题。

However if you have NavigationLinks that are chained, that is a link that leads to another list of links, then this solution will create side effects;但是,如果您有链接的 NavigationLinks,即指向另一个链接列表的链接,那么此解决方案将产生副作用; the stack returns to the origin at the second attempt to show the last view.堆栈在第二次尝试显示最后一个视图时返回原点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM