使用动态加载的数据在详细视图中的文章之间导航

问题描述 投票:0回答:1

我正在构建一个 SwiftUI 应用程序,它显示从 Firestore 获取的文章列表。该应用程序有一个显示文章的列表视图和一个显示所选文章的详细信息的详细信息视图。文章在列表视图中批量动态加载。

我尝试通过 MVVM 架构快速思考改编一些待办事项列表的示例:https://www.youtube.com/playlist?list=PLwvDm4VfkdpheGqemblOIA7v3oq0MS30i 还有 Peterfriese 的一些使用 firestore 创建待办事项列表的示例: https://peterfriese.dev/blog/2020/replicating-reminder-swiftui-firebase-part1/

但是,这些示例估计只有几个待办事项,并且在详细视图中没有在它们之间切换的选项 - 您总是返回列表视图,然后单击下一个项目返回详细视图。 使用我的 RSS 阅读器,我需要快速阅读数百篇文章 - 因此,为了不超出我的 firestore 读取限制,我需要动态加载列表,因为我的 firestore 数据库中可能有数千篇文章,但我不想加载它们都在启动时。 但随后我需要跳过与我在详细视图的列表视图中设置的某些过滤条件相匹配的所有文章。

当前的实现可以很好地显示文章列表并导航到详细视图。但是,当我尝试在详细视图中导航到下一篇或上一篇文章时,我遇到了问题。 这是相关代码的简化版本:

迅速

struct ContentView: View {
    @State private var currentIndex = 0
    @EnvironmentObject var viewModel: FirestoreDataViewModel
    
    var body: some View {
        NavigationView {
            List {
                ForEach(Array(viewModel.items.enumerated()), id: \.element.id) { index, item in
                    NavigationLink(destination: DetailView(currentIndex: $currentIndex, items: viewModel.items)) {
                        ArticleRow(item: item)
                    }
                }
            }
        }
    }
}

struct DetailView: View {
    @Binding var currentIndex: Int
    let items: [Article]
    
    var body: some View {
        // Display the detailed information of the article at the current index
        // Allow navigation to the next or previous article
    }
}

出现此问题的原因是,导航到下一篇或上一篇文章时,详细信息视图中的 currentIndex 未正确更新。列表视图中的currentIndex表示当前加载的批次文章中第一项的索引,而详细视图需要访问初始加载的批次之外的文章。

我正在寻求有关处理这种情况的最佳方法的建议,并在详细视图中的文章之间实现平滑导航。

在列表视图中批量动态加载文章时,在详细视图中访问单个文章的推荐方式是什么?

我是否应该修改应用程序的架构以更好地适应此功能?如果是这样,您建议进行哪些更改?

如何确保详细信息视图中的 currentIndex 与所显示文章的实际索引保持同步,即使导航超出了最初加载的批次?

swift google-cloud-firestore swiftui navigation detailview
1个回答
0
投票

据我了解,您的目标是在 DetailView 中获取当前文章的下一篇和上一篇文章,我建议您可以有一个函数来基于

Article
本身而不是
currentIndex
获取下一篇文章:

struct ContentView: View {
    @FocusState private var isFocus: Bool
    @State private var weight = ""
    
    var body: some View {
        HStack {
            Text("Weight")
            Spacer()
            TextField("Weight", text: $weight)
                .focused($isFocus)
            Text("kg")
            if isFocus {
                Image(systemName: "xmark.circle.fill")
            }
        }
        
    }
}

struct Article: Identifiable {
    var id: String = ""
}

struct ContentView: View {
    @State private var currentArticle: Article? = nil
    @EnvironmentObject var viewModel: FirestoreDataViewModel
    
    var body: some View {
        NavigationView {
            List {
                ForEach(Array(viewModel.items.enumerated()), id: \.element.id) { index, item in
                    NavigationLink(destination: DetailView(currentArticle: currentArticle, article: item)) {
                        ArticleRow(item: item)
                    }
                }
            }
        }
    }
}

@Observable
class FirestoreDataViewModel {
    var list: [Article] = []
    
    func getNextArticle(article: Article) -> Article? {
        guard let index = list.firstIndex(where: { $0.id == article.id }),
              index + 1 < list.count
        else { return nil }
        return list[index + 1]
    }
}

struct DetailView: View {
    @Binding var currentArticle: Article?
    @EnvironmentObject var viewModel: FirestoreDataViewModel
    
    let article: Article
    
    var body: some View {
        // Display the detailed information of the article at the current index
        // Allow navigation to the next or previous article
        Button(action: {
            currentArticle = viewModel.getNextArticle(article: article)
        }, label: {
            Text("Go Next")
        })
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.