SwiftUI中无法上传含嵌套数组的对象至Firestore求助
SwiftUI上传含数组的Order对象到Firestore失败问题
问题概述
在SwiftUI项目中,尝试将包含字符串数组的Order对象上传至Firestore时失败,已确认构造的Order数据格式正确,但上传时抛出FirestoreEncodingError。
待保存的对象示例:customer: irelyn - items: ["Chicken Bacon Ranch", "BLT"] - total price: 17.30
错误信息
The operation couldn’t be completed. (FirebaseFirestoreSwift.FirestoreEncodingError error 0.)
相关代码
保存函数
// function to save the order func saveItem(item: Order, completion: @escaping (Error?) -> ()) { let db = Firestore.firestore() let encoder = JSONEncoder() do { let data = try encoder.encode(item) let dictionary = try JSONSerialization.jsonObject(with: data, options: []) as? [String : Any] ?? [:] db.collection("items").addDocument(data: dictionary) { (error) in completion(error) } } catch { completion(error) } }
数据模型
struct Order: Identifiable, Codable { @DocumentID var id: String? let customer: String let total: String let orderItems: [String] } // the menuitem objects -> im storing the name into an array for all the items being ordered in the object above struct MenuItem: Identifiable, Codable { var id: String? var name: String var description: String var price: Double }
视图下单代码
Button { // store the menu items let array: [MenuItem] = appVM.myCart let menuItems: [String] = array.map { $0.name } let formatter = NumberFormatter() formatter.minimumFractionDigits = 2 formatter.maximumFractionDigits = 2 let price = appVM.totalAmount let orderTotal = formatter.string(for: price) ?? "" let user = loginVM.currentUser?.fullName // store the new order with total, name, and order let newOrder = Order(customer: user ?? "",total: orderTotal, orderItems: menuItems) print("customer: \(newOrder.customer) - items: \(newOrder.orderItems) - total price: \(newOrder.total)") appVM.saveItem(item: newOrder) { (error) in if let error = error { print(error.localizedDescription) } else { print("Success") } } } label: { Text("Place My Order!") .bold() .padding() .frame(maxWidth: .infinity) .background(Color.white) .cornerRadius(30) .padding(.horizontal) .foregroundColor(.orange) }
解决方案
问题出在编码方式:系统JSONEncoder无法正确处理Firebase的@DocumentID属性,导致编码失败。需改用FirebaseFirestoreSwift提供的Firestore.Encoder来编码对象。
修改后的保存函数:
func saveItem(item: Order, completion: @escaping (Error?) -> ()) { let db = Firestore.firestore() let encoder = Firestore.Encoder() // 使用Firestore专用编码器 do { let dictionary = try encoder.encode(item) db.collection("items").addDocument(data: dictionary) { error in completion(error) } } catch { completion(error) } }
注意事项
- 确保项目已导入
FirebaseFirestoreSwift框架(通过CocoaPods或Swift Package Manager添加) Order模型的Codable实现无误,所有属性符合编码要求- 无需通过
JSONSerialization二次转换,Firestore.Encoder直接输出Firestore可接受的[String: Any]格式
内容的提问来源于stack exchange,提问作者Tarun Reddy
相关产品推荐
相关产品推荐

