如何在Firestore中存储对象数组

时间:2019-03-08 18:29:54

标签: ios swift firebase google-cloud-firestore

我找不到在线存储对象数组的方法,以便键“ line_items”显示每个menuItem的数字以及每个menuItem对应于其自身数字的值。换句话说,我需要数字位于line_items之后,而不是嵌套键之后,以便可以快速引用每个单独的MenuItem对象。我在线上找到了制作方法,因此每个键都有一个值数组,但是我需要line_items才能有一个MenuItem对象数组。以下代码崩溃:

public func uploadTransactionData(_ menuItems: [MenuItem], balanceId: String, subTotal: Int, completion: @escaping (() -> ())) {
    guard let userId = Auth.auth().currentUser?.uid else { completion(); return }
    let utilitiesManager = UtilitiesManager()
    let timestamp = utilitiesManager.timestamp()
    let params: [String: Any] = ["date": "\(timestamp)",
        "balance_id": "\(balanceId)",
        "subtotal": "\(subTotal)",
        "user_id": "\(userId)",
        "line_items": menuItems
    ]
    Firestore.firestore().document("transaction_history/\(timestamp)").setData(params)
    { err in
        if let e = err {
            print("$-- error creating user \(e)")
            completion()
        } else {
            completion()
        }
    }
}

这是MenuItem模型:

struct MenuItem {

let itemId: String
let name: String
var modifiers: [String]?
var photoName: String?
var photoUrl: String?
var quantity: Int
var price: Int
var sizeAddOnPrice: Int
var toppingsAddOnPrice: Int
let description: String
var size: String
let category: String

init(itemId: String, name: String, modifiers: [String]?, photoName: String?, photoUrl: String?, quantity: Int, price: Int, sizeAddOnPrice: Int, toppingsAddOnPrice: Int, description: String, size: String, category: String) {
    self.itemId = itemId
    self.name = name
    self.modifiers = modifiers
    self.photoName = photoName
    self.photoUrl = photoUrl
    self.quantity = quantity
    self.price = price
    self.sizeAddOnPrice = sizeAddOnPrice
    self.toppingsAddOnPrice = toppingsAddOnPrice
    self.description = description
    self.size = size
    self.category = category
}

2 个答案:

答案 0 :(得分:2)

问题:

您的应用程序崩溃是因为您试图将用户定义的对象MenuItem保存到Firestore。 Firestore不允许。 Firestore仅支持this数据类型。

解决方案:

您可以将自定义对象MenuItem转换为Firestore支持的数据类型。 您可以通过对代码进行以下更改来做到这一点。

  1. 确认MenuItem符合Codable协议。

    struct MenuItem: Codable { 
         // Your code as it is.
    }
    
  2. uploadTransactionData()函数进行以下更改:

    public func uploadTransactionData(_ menuItems: [MenuItem], balanceId: String, subTotal: Int, completion: @escaping (() -> ())) {
    let userId = Auth.auth().currentUser?.uid else { completion(); return }
    let utilitiesManager = UtilitiesManager()
    let timestamp =  utilitiesManager.timestamp()
    
    var list_menuItem = [Any]()
    for item in menuItems {
        do {
            let jsonData = try JSONEncoder().encode(item)
            let jsonObject = try JSONSerialization.jsonObject(with: jsonData, options: [])
            list_menuItem.append(jsonObject)
        }
        catch {
            // handle error
        }
    }
    
    let params: [String: Any] = ["date": "\(timestamp)",
        "balance_id": "\(balanceId)",
        "subtotal": "\(subTotal)",
        "user_id": "\(userId)",
        "line_items": list_menuItem
    ]
    
    
    Firestore.firestore().document("transaction_history/\(timestamp)").setData(params) 
        { err in
            if let e = err {
                print("$-- error creating user \(e)")
                completion()
            } else {
                completion()
            }
        }
    }
    

答案 1 :(得分:0)

这是因为Firestore不知道如何保存值:menuItems

you can map it like this: "objectExample": [
    "a": 5,
    "b": [
        "nested": "foo"
    ]
]

或:

.setData([
"name": "Frank",
"favorites": [ "food": "Pizza", "color": "Blue", "subject": "recess" ],
"age": 12
])