【问题标题】:SwiftUI, Firestore get array of object within objectSwiftUI,Firestore 获取对象内的对象数组
【发布时间】:2021-05-14 18:05:36
【问题描述】:

我正在开发一个连接到 Firestore 的食谱应用程序,但无法读取保存在数据库中的数据。我保存了一个由标题、ID 等组成的食谱,但它也包含一系列成分。这个数组是一个包含 id、name 和 amount 的结构体。我能够获取配方对象,但成分数组为空。这就是获取食谱的方法

    private func listenForRecipes() {
        
        db.collection("recipe").addSnapshotListener { (querySnapshot, error) in
            guard let documents = querySnapshot?.documents else {
                print("No documents")
                return
            }
            
            self.recipes = documents.map { queryDocumentSnapshot -> RecipePost in
                let data = queryDocumentSnapshot.data()
                let title = data["title"] as? String ?? ""
                let steps = data["steps"] as? [Step] ?? []
                let ingredients = data["ingredients"] as? [Ingredient] ?? []
                let serves = data["serves"] as? Int ?? 0
                let author = data["author"] as? String ?? ""
                let authorId = data["authorId"] as? String ?? ""
                let category = data["category"] as? String ?? ""
                let image = data["image"] as? String ?? ""
                print("\(ingredients)")

                return RecipePost(title: title, steps: steps, ingredients: ingredients, serves: serves, author: author, authorId: authorId, category: category, image: image)
                
            }
        }
    }

感谢您的帮助。

【问题讨论】:

  • 这实际上很容易纠正。如果你的成分是一个字符串数组,你可以简单地做let ingredients = dataSnapshot?.get("ingredients") as? [String] ?? [String]()。这将生成一个字符串数组。要对此进行扩展,您还可以获得其他数据,但 Firestore 没有 Struct 字段类型(根据您的问题),因此我们需要知道它的实际外观。它应该很简单,但需要更多数据。

标签: swift firebase google-cloud-firestore swiftui


【解决方案1】:

您从 Firebase 获取的数据会以 [String:Any] 字典的形式返回给您。您当前的代码正在使用这些字典键(标题、作者等)并进行可选转换(as?),告诉系统“如果此数据实际上是字符串,则将我的变量设置为该值。如果不是 (? ?),这是要使用的默认值"

当您引入自定义类型时,问题就来了。系统本身并不知道您的项目是Ingredient 或Step。因此,强制转换失败,您将获得默认值 []。

你有两个选择:

  1. 为整个文档使用自定义类型(请参阅此处的 Firebase 文档:https://firebase.google.com/docs/firestore/query-data/get-data#swift_3)。这个 SO 问题也很相关:How to convert document to a custom object in Swift 5?

  2. 自己转换[String:Any] 字典(或本例中的字典数组)。第一步可能是 print data["ingredients"] 到控制台,看看它真正有什么。由于无法查看您在 Firestore 中实际拥有的内容,我们假设它是 [[String:Any]](字典数组)。那么您的转换可能如下所示:

let ingredients = (data["ingredients"] as? [[String:Any]]).map { item in
  return Ingredient(id: item["id"] as? String ?? "", name: item["name"] as? String ?? "", amount: item["amount"] as? String ?? "")
}

您还可以尝试使用Codable,这可以让您自动化其中的一些过程,例如使用JSONDecoder 为您完成一些工作。相关SO:How can I use Swift’s Codable to encode into a dictionary?

【讨论】:

  • 感谢您的回答!我努力让它发挥作用,最终将成分和步骤保存在与食谱相同的文档下的不同集合中。
猜你喜欢
  • 1970-01-01
  • 2016-08-29
  • 2018-08-12
  • 2021-07-25
  • 2021-08-22
  • 2019-11-10
  • 1970-01-01
  • 1970-01-01
  • 2013-12-19
相关资源
最近更新 更多