You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.25 17:22:54