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
相关产品推荐
相关产品推荐

