首页 > 解决方案 > 从firestore返回数组

问题描述

swiftui 和 firestore 的新手,在调用这个文档数组时遇到了困难。希望有人可以帮助我解决将“项目”数组调用到 VStack 中的代码。

在此处输入图像描述

添加了我一直在尝试的代码

查看模型

import SwiftUI
import FirebaseFirestore

class MovieItemViewModel: ObservableObject {
    
    @Published var movieItems = [MovieItem]()
    
    private var db = Firestore.firestore()
    
    func fetchData() {
        db.collection("movies").order(by: "items").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No Documents")
                return
            }
            
                self.movieItems = documents.map { (queryDocumentSnapshot) -> MovieItem in
                let data = queryDocumentSnapshot.data()
                
                let items = data["items"] as? String ?? ""
                    
                return MovieItem(item: items)
                
            }
            
        }
    }
}

模型

import SwiftUI

struct MovieItem: Identifiable {
    var id: String = UUID().uuidString
    var item: String
}

主视图

struct MovieDetailListView: View {
    
    @ObservedObject private var viewModel = MovieItemViewModel()

    var body: some View {

     VStack(alignment: .leading, spacing: 15){
        ForEach(viewModel.movieItems.indices, id: \.self) { i in
        Text(viewModel.movieItems[i].item) 
        } 
     }
     .onAppear() { self.viewModel.fetchData() }
}
}

标签: swiftfirebasegoogle-cloud-firestoreswiftui

解决方案


代码中的问题很少。让我先解决 Firebase 问题

.collection("movies").order(by: "items")

不正确,因为 items 不是电影的文档子项。然而590706是。因此,如果目标是读取 590706 内的项目,则需要指定该路径。

此外,.addSnapshotListener在该路径上留下一个观察者/侦听器,如果有任何更改,将触发一个事件并将这些更改传递给您的应用程序。看起来你(还)不想要那个 - 看起来你只是想按需读取数据(例如,当用户选择电影时)

这是将读取您询问的数据的代码。为简洁起见,我省略了任何错误检查

func readMovieItems() {
    let movieNum = "590706"
    let refToRead = self.db.collection("movies").document(movieNum)
    refToRead.getDocument(completion: { documentSnapshot, error in
        if let err = error {
             print(err.localizedDescription)
             return
         }

        if let doc = documentSnapshot {
            let title = doc.get("movie") as! String
            let items = doc.get("items") as! [String]
            print(title)
            for item in items {
                print(item)
            }
        }
    })
}

从那里开始,您有很多选择;假设这是一个 Master->Detail 设置,其中包含在 master 上的电影列表,当点击电影时,详细信息会显示在详细信息视图中。这样的事情会做到

struct MasterView: View {
    @Binding var movies: [MovieClass]

    var body: some View {
        List {
            ForEach(movies, id: \.self) { movie in
                NavigationLink(
                    destination: DetailView(selectedMovie: movie)
                ) {
                    Text("\(movie.title)")
                }
            }.onDelete { indices in
                indices.forEach { self.movies.remove(at: $0) }
            }
        }
    }
}

推荐阅读