【问题标题】:NavigationLink freezes when trying to revisit previously clicked NavigationLink in SwiftUI尝试重新访问 SwiftUI 中先前单击的 NavigationLink 时,NavigationLink 冻结
【发布时间】:2020-03-31 16:34:19
【问题描述】:

我正在设计一个应用程序,该应用程序包括检索 JSON 数据并在 FileBrowser 类型视图中显示检索项目列表的功能。在此视图中,用户应该能够单击文件夹以深入了解文件树或单击文件以查看有关该文件的一些元数据。

我观察到,当我单击文件或文件夹然后返回并再次单击它时,NavigationLink 不会被触发,并且我会卡在视图上,直到我单击另一个 NavigationLink。

这是一个演示这个问题的 gif。

如此处所示,当我单击 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)
                }
        }
    }
}

并通过如下方式使用 navigationLinks 进入视图

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 中并从FileView 中删除NavigationView 吗?我在这里看到了一些这样做的例子。
  • @GiovanniTerlingen 除非我误解了你的意思,否则这就是我正在做的事情。 NavigationLinkFileView 的内部,它被包裹在 NavigationView 中,因此 NavigationLink 被包裹在 NavigationView 的内部
  • 请提供最小可运行项目。我无法重现这个,所以它可能不是 SwiftUI 的错误之一。
  • 您能否提供完整的源代码,以便我解决您的问题
  • 你是如何准备cellArray的?

标签: ios swift swiftui swiftui-list swiftui-navigationlink


【解决方案1】:

遇到同样的问题 - 试试这个。当 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)

基本上似乎在某些情况下(iOS 13.3 - 模拟器?)当目标视图从导航堆栈中删除时,NavigationLink 不会重置。作为一种解决方法,我们需要重新生成导航链接。这就是更改 id 的作用。这纠正了我的问题。

但是,如果您有链接的 NavigationLinks,即指向另一个链接列表的链接,那么此解决方案将产生副作用;堆栈在第二次尝试显示最后一个视图时返回原点。

【讨论】:

  • 这个bug在最新的IOS版本中得到修复。我将此标记为正确答案,因为它可以解决问题,但是,这不应该是一个问题。我也喜欢你对问题的解释。谢谢。
  • 当您说最新的 iOS 版本时,您是指 13.4 还是 beta 版本?
  • 我也想知道。哪个版本运行正确?我有 13.3(这是目前最新的 iOS),但问题仍然存在。
  • 我相信这个错误是在 IOS 13.3 beta 版本中出现的,但在 IOS 13.3 Beta 4 中已经修复。
猜你喜欢
  • 2023-04-04
  • 2020-01-08
  • 2020-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-07-18
  • 1970-01-01
相关资源
最近更新 更多