SwiftUI 嵌套导航

4
当我导航时,下一页会快速打开和关闭。为什么?

enter image description here

我在一个空项目上尝试了这个,没有遇到这个问题。为什么在我的项目中前进后导航会回来? 我想创建一个嵌套导航结构。

我的项目代码:

应用程序

@main
struct FileApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .onAppear {
                    UserDefaults.standard.set(false, forKey: "_UIConstraintBasedLayoutLogUnsatisfiable")
                }
        }
    }
}

ContentView:

struct ContentView: View {
    @StateObject var safeFileVM: SafeFileViewModel = SafeFileViewModel()
    var body: some View {
        NavigationView {
            AView(safeFileVM: safeFileVM)
        }
    }
}

AView:

struct AView: View {
    @ObservedObject var safeFileVM: SafeFileViewModel
    
    @State var currentLocation = ""
    @State var currentFolder: String = "Safe File"
    var body: some View {
        List(safeFileVM.arrayOfFiles, id: \.id) { folderItem in
            BView(safeFileVM: safeFileVM, currentFile: folderItem, currentLocation: currentLocation)
        }
        .navigationTitle(Text(currentFolder))
        .onAppear {
            safeFileVM.additionPath = currentLocation
            safeFileVM.takeArrayOfItems()
        }
    }
} 

BView:

struct BView: View {
    @ObservedObject var safeFileVM: SafeFileViewModel
    @State var currentFile: MyFile
    @State var currentLocation: String
    var body: some View {
        VStack {
            if currentFile.typeOfFile == "folder" {
                NavigationLink(currentFile.fileName) {
                    AView(safeFileVM: safeFileVM, currentLocation: currentLocation + "/" + currentFile.fileName, currentFolder: currentFile.fileName)
                }
                .isDetailLink(false)
            } else {
                Text(currentFile.fileName)
            }
        }
    }
}

空项目代码:

内容视图:

struct ContentView: View {
    var body: some View {
        NavigationView {
            AView()
                .navigationBarTitleDisplayMode(.inline)
        }
    }
}

AView:

struct AView: View {
    var body: some View {
        List(0..<5) { item in
            BView(title: item)
        }
    }
}

BView:

struct BView: View {
    var title: Int = 0
    var body: some View {
        NavigationLink("test \(title)") {
            AView()
        }
    }
}

这个项目从来没有使用过NavigationView,因为每个屏幕都有自己的链接堆栈,所以请忘记NavigationView并继续使用数据驱动的NavigationStack。 - Asperi
将 @State var currentFile: MyFile 更改为 let currentFile: MyFile。 - malhal
虽然你不应该使用AView无限递归引用BView,以及BView引用AView。但是你的“EMPTY PROJECT CODES:”在我使用ios 15.5上出奇地有效。在macOS 12.5,Xcode 14,目标ios-15.5上也同样有效。 - workingdog support Ukraine
你的“MY PROJECT CODES:”无法编译,因此无法进行测试,它缺少一些部分,例如SafeFileViewModelMyFile。请展示能够重现问题的代码。 - workingdog support Ukraine
1个回答

1
在你的AViewonAppear中,你调用takeArrayOfItems,我猜它会改变视图模型中的.arrayOfFiles属性。
在你的层次结构中,你的顶层AView创建了一个项目列表,这些项目链接到BViewBView中的文件夹链接再次链接到AView
当嵌套的AView被调用时,onAppear会再次被调用 - 所以takeArrayOfItems可能会改变根目录的文件夹,从而使路径更深层次的链接无效;因此导航视图将自己重置回根目录。
你应该注意确保你的层次结构刷新不会使驱动UI的数据无效。观看WWDC21中的Demystifying SwiftUI也可能很有用,其中介绍了SwiftUI如何使用对象标识来确定何时需要重新绘制界面,等等。

如果您的应用程序只能在iOS16上运行,那么您也可以访问SwiftUI中的新导航UI组件,这些组件提供了由状态对象数组驱动的堆栈,使得在数据发生变化时更容易维护堆栈位置。有关此主题的有用视频是来自WWDC22的The SwiftUI cookbook for navigation


这是一个很好的解释,它帮助我很多,让我弄清楚了我的导航出了什么问题。谢谢! - VoodooBoot

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接