Swift Firebase-如何通过嵌入式结构读取此地图?

Swift Firebase-如何通过嵌入式结构读取此地图?,swift,firebase,uitableview,google-cloud-firestore,Swift,Firebase,Uitableview,Google Cloud Firestore,我正在从Firestore读取数据,以便能够填充到扩展的tableview单元格中。我有一个非常简单的结构: protocol PlanSerializable { init?(dictionary:[String:Any]) } struct Plan{ var menuItemName: String var menuItemQuantity: Int var menuItemPrice: Double var dictionary: [Strin

我正在从Firestore读取数据,以便能够填充到扩展的tableview单元格中。我有一个非常简单的结构:

protocol PlanSerializable {
    init?(dictionary:[String:Any])
}

struct Plan{
    var menuItemName: String
    var menuItemQuantity: Int
    var menuItemPrice: Double

    var dictionary: [String: Any] {
        return [
            "menuItemName": menuItemName,
            "menuItemQuantity": menuItemQuantity,
            "menuItemPrice": menuItemPrice
        ]
    }
}

extension Plan : PlanSerializable {
    init?(dictionary: [String : Any]) {
        guard let menuItemName = dictionary["menuItemName"] as? String,
            let menuItemQuantity = dictionary["menuItemQuantity"] as? Int,
            let menuItemPrice = dictionary["menuItemPrice"] as? Double

        else { return nil }

        self.init(menuItemName: menuItemName, menuItemQuantity: menuItemQuantity, menuItemPrice: menuItemPrice)
    }
}
这是嵌入在这个结构中的:

protocol ComplainSerializable {
    init?(dictionary:[String:Any])
}

struct Complain{
    var status: Bool
    var header: String
    var message: String
    var timeStamp: Timestamp
    var email: String
    var planDetails: Plan

    var dictionary: [String: Any] {
        return [
            "status": status,
            "E-mail": header,
            "Message": message,
            "Time_Stamp": timeStamp,
            "User_Email": email,
            "planDetails": planDetails
        ]
    }
}

extension Complain : ComplainSerializable {
    init?(dictionary: [String : Any]) {
        guard let status = dictionary["status"] as? Bool,
            let header = dictionary["E-mail"] as? String,
            let message = dictionary["Message"] as? String,
            let timeStamp = dictionary["Time_Stamp"] as? Timestamp,
            let email = dictionary["User_Email"] as? String,
            let planDetails = dictionary["planDetails"] as? Plan

        else { return nil }

        self.init(status: status, header: header, message: message, timeStamp: timeStamp, email: email, planDetails: planDetails)
    }
}
但是,我无法从Firestore查询任何如下数据:

这是我的查询,尽管我正在读取所有文件:

let db = Firestore.firestore()
var messageArray = [Complain]()

func loadMenu() {
        db.collection("Feedback_Message").getDocuments() { documentSnapshot, error in
            if let error = error {
                print("error:\(error.localizedDescription)")
            } else {
                self.messageArray = documentSnapshot!.documents.compactMap({Complain(dictionary: $0.data())})
                for plan in self.messageArray {
                    print("\(plan.email)")
                }
                DispatchQueue.main.async {
                    self.testTable.reloadData()
                }
            }
        }
    }
我做错了什么? 编辑: 根据建议,以下是更新的嵌入式结构:

import Foundation

// MARK: - Complain
struct Complain: Codable {
    let eMail, message, timeStamp, userEmail: String
    let status: Bool
    let planDetails: PlanDetails

    enum CodingKeys: String, CodingKey {
        case eMail = "E-mail"
        case message = "Message"
        case timeStamp = "Time_Stamp"
        case userEmail = "User_Email"
        case status, planDetails
    }
}

// MARK: - PlanDetails
struct PlanDetails: Codable {
    let menuItemName: String
    let menuItemQuantity: Int
    let menuItemPrice: Double
}

使用quicktype.io,可以生成结构。从这里开始,您所需要做的就是在响应处理程序中运行这段代码

    var compainArray = [Complain]()
func loadMenu() {
    db.collection("Feedback_Message").getDocuments() { documentSnapshot, error in
        if let error = error {
            print("error:\(error.localizedDescription)")
        } else {
            guard let snapshot = documentSnapshot else {return}

            for document in snapshot.documents {
                if let jsonData = try? JSONSerialization.data(withJSONObject: document.data()){
                    if let converted = try? JSONDecoder().decode(Complain.self, from: jsonData){
                        self.compainArray.append(converted)
                    }
                }
            }
            DispatchQueue.main.async {
                self.testTable.reloadData()
            }
        }
    }
}

它将处理某些变量的循环和映射。如果你对此有任何问题,请告诉我

看看如何使用。将为您生成结构。此外,您不会循环查看计划详细信息,也不会访问其第一个元素,因此响应为空。如果将字典应用于整个快照,我将如何循环查看映射?我现在是否必须循环浏览快照中的每个文档,并在每个循环中循环浏览所有映射?请查看quicktype.io并告诉我您的操作过程?使用Decodables将消除很多麻烦。我按照建议更新了结构。由于没有字典,我将不得不循环浏览快照(这很好),但如何循环浏览映射(我完全被它弄糊涂了)。我生成了结构(它位于原始文章的底部)。AppDelegate中出现错误:“JSON写入(FIRQueryDocumentSnapshot)中的类型无效”。此时我不确定结构或响应处理程序是否有问题。@BVB09我已更新为代码,很抱歉之前不清楚。无需使用JSON序列化从Firestore快照获取数据。快照属性是一个
QuerySnapshot
,文档属性是一个
FIRDocumentSnapshot
数组。您所需要做的就是迭代数组并使用内置的
get()
方法,该方法专门用于避免使用JSON序列化。前几天我为OP回答了这个问题,但看起来他又回到了老习惯。嗨,bsod,很抱歉你在另一个帖子中提供了正确的答案。我应该澄清一下,结构本身并没有在我用来填充表的主数组中创建映射数组。