Swift映射Firebase查询结果到模型时出现无参数调用传参错误
问题1:Conversations 初始化报错「Argument passed to call that takes no arguments」
原因
Swift 中只有结构体类型会自动生成成员级构造器,类类型不会。你为 Conversations 类的所有属性都设置了默认值,系统只会自动生成无参构造器 Conversations(),不支持直接传入属性值初始化。
修复方案
给 Conversations 类添加自定义带参构造器:
class Conversations: Decodable, Identifiable, ObservableObject { var id: String = "" var users: [String] = [""] var messages: [Message] = [] var hasUnreadMessage : Bool = false // 新增带参构造器 convenience init(id: String, users: [String], messages: [Message], hasUnreadMessage: Bool) { self.init() self.id = id self.users = users self.messages = messages self.hasUnreadMessage = hasUnreadMessage } // 如果使用Firestore自动解码,建议添加以下配置 enum CodingKeys: String, CodingKey { case id, users, messages, hasUnreadMessage } }
问题2:Message 结构体不符合Decodable协议要求
原因
三个点共同导致:
- 内部枚举
MessageType没有遵守Decodable协议 - 你自定义了两个构造方法,编译器无法自动合成Decodable所需的解码构造器
id属性是本地生成的UUID,不需要从服务端解码,需要明确排除在解码字段外
修复方案
调整 Message 结构体代码如下:
struct Message: Decodable, Identifiable { // 让枚举遵守Decodable,指定原始值类型方便和服务端字符串映射 enum MessageType: String, Decodable { case Sent, Received } let id = UUID() let date: Date let text: String let type: MessageType? // 指定解码时忽略id字段 enum CodingKeys: String, CodingKey { case date, text, type } // 保留原有自定义构造方法 init(_ text: String, type: MessageType, date: Date) { self.date = date self.text = text self.type = type } init(_ text: String, type: MessageType) { self.init(text, type: type, date: Date()) } // 手动实现解码逻辑 init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) date = try container.decode(Date.self, forKey: .date) text = try container.decode(String.self, forKey: .text) type = try container.decodeIfPresent(MessageType.self, forKey: .type) } }
额外优化建议
你当前代码中 let msgs = data["messages"] as? [Message] ?? [] 这行永远会返回空数组,因为Firestore返回的数组元素是字典类型,无法直接强转成自定义的Message类型。推荐使用Firestore官方的Codable支持简化映射逻辑:
- 导入
FirebaseFirestoreSwift库 - 把原有手动映射的代码替换为:
self.chats = documents.compactMap { queryDocumentSnapshot in try? queryDocumentSnapshot.data(as: Conversations.self) }
无需手动逐个读取字段,Firestore会自动完成所有属性的解码,还会自动处理嵌套的Message数组解析。
内容的提问来源于stack exchange,提问作者Nat Serrano
相关产品推荐
相关产品推荐

