You need to enable JavaScript to run this app. Swift中如何为枚举设置动态可变CodingKeys适配Firestore Codable存储
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何为枚举设置动态可变CodingKeys适配Firestore Codable存储

解决方案

可以通过自定义CodingKeys实现需求,但不能用枚举类型的CodingKeys(枚举的RawValue必须是编译期确定的常量,不支持运行时动态拼接值),你需要换成遵循CodingKey协议的自定义结构体,配合手动实现编解码逻辑即可完成动态编码键的需求。

完整实现代码

struct MyStruct: Codable {
    let userID: String
    let userName: String
    let useCase: String
    
    // 自定义支持动态键的CodingKey实现,替代原枚举
    private struct DynamicCodingKey: CodingKey {
        let stringValue: String
        let intValue: Int?
        
        init?(stringValue: String) {
            self.stringValue = stringValue
            self.intValue = nil
        }
        
        init?(intValue: Int) {
            self.intValue = intValue
            self.stringValue = "\(intValue)"
        }
        
        // 便捷初始化方法,直接传入自定义键名
        init(key: String) {
            self.stringValue = key
            self.intValue = nil
        }
    }
    
    // 手动实现编码逻辑
    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: DynamicCodingKey.self)
        // 编码静态键字段
        try container.encode(userID, forKey: DynamicCodingKey(key: "id"))
        try container.encode(userName, forKey: DynamicCodingKey(key: "name"))
        // 生成动态键并编码
        let dynamicKey = "use_case_\(Int.random(in: 0..<100))"
        try container.encode(useCase, forKey: DynamicCodingKey(key: dynamicKey))
    }
    
    // 仅需要存储到Firestore不需要读取的话可以删除下面的解码实现
    init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: DynamicCodingKey.self)
        // 解码静态键字段
        userID = try container.decode(String.self, forKey: DynamicCodingKey(key: "id"))
        userName = try container.decode(String.self, forKey: DynamicCodingKey(key: "name"))
        // 匹配前缀为use_case_的动态键解码
        guard let useCaseKey = container.allKeys.first(where: {
            $0.stringValue.hasPrefix("use_case_")
        }) else {
            throw DecodingError.dataCorrupted(.init(
                codingPath: decoder.codingPath,
                debugDescription: "Missing use_case_ prefixed dynamic key"
            ))
        }
        useCase = try container.decode(String.self, forKey: useCaseKey)
    }
    
    // 便捷初始化方法
    init(userID: String, userName: String, useCase: String) {
        self.userID = userID
        self.userName = userName
        self.useCase = useCase
    }
}

适配Firestore的使用说明

你可以直接用Firestore自带的Codable扩展将该结构体实例写入数据库,生成的文档会自动携带use_case_前缀加随机数的动态键,符合你的需求。如果不需要从Firestore读取该结构体数据,可以删除init(from:)方法的实现,进一步简化代码。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.10 09:18:03