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

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支持简化映射逻辑:

  1. 导入 FirebaseFirestoreSwift 库
  2. 把原有手动映射的代码替换为:
self.chats = documents.compactMap { queryDocumentSnapshot in
    try? queryDocumentSnapshot.data(as: Conversations.self)
}

无需手动逐个读取字段,Firestore会自动完成所有属性的解码,还会自动处理嵌套的Message数组解析。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.01 13:18:04