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

Firebase实时数据库数据解析失败问题求助

问题分析与解决方案

错误根源

你代码中尝试将snapshot.value强制转换为[[String: Any]](数组类型),但从打印结果来看,snapshot.value实际是单个[String: Any]字典结构,类型不匹配直接触发了Failed to parse conversations错误。


解决方案

根据你当前的数据库结构(conversations节点下为单个对话对象),修改解析逻辑如下:

1. 修正解析函数

public func getConversation(with email: String, completion: @escaping(Result<Conversation?, Error>) -> Void) {
    database.child("\(email)/conversations").observeSingleEvent(of: .value) { snapshot in
        // 先判断节点是否存在数据
        guard snapshot.exists() else {
            completion(.success(nil))
            return
        }
        
        // 将快照转为单个字典,而非数组
        guard let value = snapshot.value as? [String: Any] else {
            print("Failed to parse snapshot value")
            let error = NSError(domain: "", code: 0, userInfo: [NSLocalizedDescriptionKey: "Failed to parse conversations"])
            completion(.failure(error))
            return
        }
        
        // 解析单个对话数据
        guard let conversationId = value["id"] as? String else {
            let error = NSError(domain: "", code: 1, userInfo: [NSLocalizedDescriptionKey: "Failed to parse conversation ID"])
            completion(.failure(error))
            return
        }

        guard let latestMessageDict = value["latest_message"] as? [String: Any],
              let message = latestMessageDict["message"] as? String,
              let date = latestMessageDict["date"] as? String,
              let isRead = latestMessageDict["is_read"] as? Int else {
            let error = NSError(domain: "", code: 2, userInfo: [NSLocalizedDescriptionKey: "Failed to parse latest message"])
            completion(.failure(error))
            return
        }

        guard let name = value["name"] as? String,
              let otherUserEmail = value["other_user_email"] as? String else {
            let error = NSError(domain: "", code: 3, userInfo: [NSLocalizedDescriptionKey: "Failed to parse name or other user email"])
            completion(.failure(error))
            return
        }

        let latestMessageObject = LatestMessage(date: date, isRead: isRead, message: message)
        let conversation = Conversation(id: conversationId, latestMessage: latestMessageObject, name: name, otherUserEmail: otherUserEmail)
        completion(.success(conversation))
    }
}

2. 调整调用逻辑

private func startListeningForConversations(){
    guard let email = UserDefaults.standard.value(forKey: "email") as? String else {
        return
    }
    let safeEmail = DatabaseManager.safeEmail(email: email)
    print(safeEmail)
    DatabaseManager.shared.getConversation(with: safeEmail) { [weak self] result in
        switch result {
        case .success(let conversation):
            if let conversation = conversation {
                print(conversation)
            } else {
                print("No conversations found")
            }
        case .failure(let error):
            print("Error fetching conversation: \(error.localizedDescription)")
        }
    }
}

扩展建议(多对话场景)

如果未来需要存储多个对话,推荐使用Firebase官方推荐的字典式结构(用childByAutoId()生成唯一key存储每个对话),此时解析逻辑应改为:

public func getConversations(with email: String, completion: @escaping(Result<[Conversation], Error>) -> Void) {
    database.child("\(email)/conversations").observeSingleEvent(of: .value) { snapshot in
        guard let conversationsDict = snapshot.value as? [String: [String: Any]] else {
            completion(.success([]))
            return
        }
        
        let conversations: [Conversation] = conversationsDict.values.compactMap { dictionary in
            guard let conversationId = dictionary["id"] as? String else { return nil }
            guard let latestMessageDict = dictionary["latest_message"] as? [String: Any],
                  let message = latestMessageDict["message"] as? String,
                  let date = latestMessageDict["date"] as? String,
                  let isRead = latestMessageDict["is_read"] as? Int else { return nil }
            guard let name = dictionary["name"] as? String,
                  let otherUserEmail = dictionary["other_user_email"] as? String else { return nil }
            
            let latestMessage = LatestMessage(date: date, isRead: isRead, message: message)
            return Conversation(id: conversationId, latestMessage: latestMessage, name: name, otherUserEmail: otherUserEmail)
        }
        completion(.success(conversations))
    }
}

内容的提问来源于stack exchange,提问作者Jonathan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.29 20:07:09