SwiftUI:如何迭代 Cloud Firestore 集合中的文档并获取数据?

时间:2021-02-25 23:06:31

标签: ios database google-cloud-firestore swiftui

我有一个小项目,用户可以在其中发布图片和报价,然后我想在他们的个人资料中以及其他地方显示图片和报价,以便其他用户可以看到帖子。< /p>

如果我有这个 Cloud Firestore 设置 其中所有 Image Docs 都具有相同的 3 个字段,但具有不同的值。

然后我如何遍历所有图像文档并获得网址引用?所以我以后可以显示网址和正确的报价吗? enter image description here

如果由于某种原因这是不可能的,那么是否有可能获得集合中的文档数量?

顺便说一句,我不是很有经验,所以如果可能的话,我会很感激“孩子友好”的回答

1 个答案:

答案 0 :(得分:1)

Firestore
  .firestore()
  .collection("Images")
  .getDocuments { (snapshot, error) in
     guard let snapshot = snapshot, error == nil else {
      //handle error
      return
    }
    print("Number of documents: \(snapshot.documents.count ?? -1)")
    snapshot.documents.forEach({ (documentSnapshot) in
      let documentData = documentSnapshot.data()
      let quote = documentData["Quote"] as? String
      let url = documentData["Url"] as? String
      print("Quote: \(quote ?? "(unknown)")")
      print("Url: \(url ?? "(unknown)")")
    })
  }

您可以通过调用 getDocuments 来获取集合中的所有文档。

在其中,snapshot 将是可选的——如果查询成功,它将返回数据。您可以看到 I upwrap snapshot 并检查 error 语句中的 guard

获得快照后,您可以使用 documents.forEach 遍历文档。在每个文档上,调用 data() 将获得一个类型为 [String:Any] 的字典。

然后,您可以从字典中请求键并尝试将它们转换为 String

你现在就可以了,我正在将所有数据打印到控制台。

请记住,getDocuments 是一个异步函数。这意味着它会运行,然后在未来某个未指定的时间返回。这意味着您可以仅使用此函数的 return 值,并期望它们在调用后立即可用。相反,您将不得不依赖于诸如设置属性之类的事情,并且可能使用回调函数或组合来告诉程序的其他部分已收到此数据。

如果这是在 SwiftUI 中,您可以通过拥有一个视图模型然后显示获取的数据来实现:

struct ImageModel {
  var id = UUID()
  var quote : String
  var url: String
} 

class ViewModel {
  @Published var images : [ImageModel] = []

  func fetchData() { 
    
    Firestore
   .firestore()
   .collection("Images")
   .getDocuments { (snapshot, error) in
      guard let snapshot = snapshot, error == nil else {
      //handle error
      return
    }
    print("Number of documents: \(snapshot.documents.count ?? -1)")
    self.images = snapshot.documents.compactMap { documentSnapshot -> ImageModel? in
      let documentData = documentSnapshot.data()
      if let quote = documentData["Quote"] as? String, let url = documentData["Url"] as? String {
         return ImageModel(quote: quote, url: url)
      } else {
         return nil
      }
    }
   }
  }
}

struct ContentView {
  @ObservedObject var viewModel = ViewModel()

  var body : some View {
    VStack {
      ForEach(viewModel.images, id: \.id) { item in 
        Text("URL: \(item.url)")
        Text("Quote: \(item.quote)")
      }
    }.onAppear { viewModel.fetchData() }
  }
} 

注意:现在有更奇特的方法可以使用 FirebaseFirestoreSwift 和 Combine 将对象从 Firestore 中解码出来,但这有点超出了这个答案的范围,它显示了基础