将 Firestore 数据分配给自定义对象

Assigning firestore data to custom object

我正在尝试制作一个使用 Firestore 来存储客户特定规格的应用。我有一个目前只有几个属性的 spec 对象,但我需要获取数据并将其分配给一个新的 Spec 对象,然后将其附加到一个数组以显示在 tableView 上。我不明白如何访问数组中的各个映射以将值分配给规范的每个 属性。我目前将它设置为在控制台中打印,因为每次我尝试从文档中分配一个值时它都是 nil。本质上,我需要在客户下存储数据(所有客户的总列表),在其他数据中有一个规格数组,其中包含每个客户的 specNumber、specDescription 和 palletCount。

示例:

Customer: Test
Specs:
3096:
    Description: 50#top
    pltCount: 250
3097:
    Description: 50#bottom
    pltCount: 250

Firestore 数据: enter image description here

代码:

    let settings = FirestoreSettings()
    
    Firestore.firestore().settings = settings
    
    db = Firestore.firestore()
    
    
    db.collection("customers/test/specs")//.whereField("isCustomer", isEqualTo: true)
        .getDocuments() { (querySnapshot, err) in
            if let err = err {
                print("Error getting documents: \(err)")
            } else {
                for document in querySnapshot!.documents {

                    print("\(document.documentID) => \(document.data())")
                    
                }
            }
    }

规范调用代码:

struct Spec {
    
    // Properties
    var specNumber: String
    var specDescription: String
    var palletCount: Int
    //var palletsOrdered = 0

    init(specNum: Int, specDesc: String, pltCount: Int) {

        specNumber = "\(specNum)"
        specDescription = specDesc
        palletCount = pltCount

    } 
}

您必须将对文档的访问与对文档中数据的访问分开(您尝试同时进行)。您不能在文档或文档中的字段上调用 ​​getDocuments(),只能在集合上调用。因此,请尝试使用

而不是 db.collection("customers/test/specs").getDocuments()
db.collection("customers").getDocuments() { (snapshot, error) in ... }

然后从文档中获取数据:

db.collection("customers").getDocuments() { (snapshot, error) in
    if let snapshot = snapshot { // lead by unwrapping the snapshot instead of the error
        for doc in snapshot.documents { // iterate through the documents
            guard let specs = doc.get("specs") as? [[String: Any]] else {
                continue // continue loop
            }
            for s in specs { // iterate through the array of specs
                if let specNum = s["SpecNum"] as? String,
                    let specDesc = s["SpecDesc"] as? String,
                    let pltCount = s["PalletCount"] as? Int {
                        let spec = Spec(specNum: specNum, specDesc: specDesc, pltCount: pltCount)
                        self.someArray.append(spec)
                    }
            }

            self.tableView.reloadData() // loop is done, reload
        }
    } else {
        if let error = error {
            print(error)
        }
    }
}

这是我想象中您实际想要实现它的方式的一个非常简化的版本,具体取决于 table/collection 的重新加载方式(即时、定期或仅一次)。此外,每个文档都包含一个规格数组,但您要从集合中获取所有文档,这会为您提供大量规格,而没有任何迹象表明哪个规格与哪个客户相关联。但我怀疑这只是早期设置,您只是想先了解 API。

注意:Firestore 中的地图在 Swift 中称为字典,它们总是作为 [String: Any] 字典从 Firestore 返回。这就是为什么当我们最初展开规格图时,我们将其转换为字典数组:

let specs = doc.get("specs") as? [[String: Any]]