Swift读取Firebase Realtime Database数据报错排查与解决
问题分析与解决方法
核心问题1:字段名不匹配
数据库中存储的字段是total_amount_send,但你的TransactionByDate模型里定义的是total_amount_sent(末尾多了一个t),字段名不一致直接导致解析失败。
核心问题2:Transactions结构不兼容
数据库里的transactions是键值对字典(键是Firebase自动生成的ID,比如-NRZfbq2xYhHF-v1beKC),但模型中定义的是数组[Transactions]。FirebaseDatabaseSwift无法直接将字典结构解析为数组类型,这是解析报错的主要原因。
次要问题:错误处理逻辑不当
在compactMap中捕获错误后返回了TransactionByDate(),这会让无效的空对象混入结果数组,应该返回nil让compactMap自动过滤掉解析失败的数据。
解决方法
步骤1:修正模型字段名与结构
把模型里的字段名改成和数据库一致,同时将transactions的类型调整为字典,匹配数据库结构:
struct TransactionByDate: Identifiable, Codable { var id: String? var total_amount_send: Int? // 修正字段名,与数据库一致 var total_amount_receive: Int? var transactions: [String: Transactions]? // 改为字典类型 } struct Transactions: Identifiable, Codable { var id: String? var amount: Int? var date: String? var detail: String? var image: String? var type: String? }
步骤2:修正数据解析逻辑
调整getEntries函数的错误处理,同时可按需将字典转为带ID的数组:
func getEntries(userId: String) { Database.database().reference().child("Transaction_By_Date").child(userId).observe(.value) { snapshot in guard let children = snapshot.children.allObjects as? [DataSnapshot] else { return } let transactionsData = children.compactMap { dateSnapshot in do { var transaction = try dateSnapshot.data(as: TransactionByDate.self) transaction.id = dateSnapshot.ref.key // 可选:将transactions字典转为带ID的数组 if let transDict = transaction.transactions { let transArray = transDict.map { key, trans in var mutableTrans = trans mutableTrans.id = key return mutableTrans } // 可将transArray赋值给模型新增的数组字段,或直接使用 } return transaction } catch let error { print(error.localizedDescription) return nil // 返回nil,过滤无效数据 } } print(transactionsData) } }
可选优化:自定义解码保持数组类型
如果一定要让模型中的transactions是数组,可以自定义解码方法,手动将字典转为数组:
struct TransactionByDate: Identifiable, Codable { var id: String? var total_amount_send: Int? var total_amount_receive: Int? var transactions: [Transactions]? enum CodingKeys: String, CodingKey { case total_amount_send, total_amount_receive, transactions } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) total_amount_send = try container.decodeIfPresent(Int.self, forKey: .total_amount_send) total_amount_receive = try container.decodeIfPresent(Int.self, forKey: .total_amount_receive) // 手动将字典转为带ID的数组 if let transDict = try container.decodeIfPresent([String: Transactions].self, forKey: .transactions) { transactions = transDict.map { key, trans in var mutableTrans = trans mutableTrans.id = key return mutableTrans } } } }
完成以上修改后,即可正确解析Firebase Realtime Database中的数据。
内容的提问来源于stack exchange,提问作者Taimoor Arif
相关产品推荐
相关产品推荐

