为什么使用_作为参数外部标签的Codable枚举会编译报错
问题原因分析
Swift 对遵循 Codable 协议的带关联值枚举,默认会自动合成编解码逻辑,合成规则为:
- 把枚举 case 名作为编码后数据的类型标识
- 把 case 关联值的外部参数标签作为关联值字段的编码key
你遇到的编译报错本质是 Swift 目前的 Codable 自动合成逻辑,不支持关联值外部标签为 _(即无外部参数名)的枚举:
- 第一个枚举
ThisEnumCompiles不需要遵循Codable,不会触发编解码逻辑合成,所以可以正常编译 - 第二个枚举
ThisEnumAlsoCompiles的关联值有明确的外部参数标签string/int,符合自动合成的规则要求,所以编译正常 - 第三个枚举
ThisEnumDoesNot的关联值用_省略了外部参数名,自动合成逻辑会尝试查找带参数名的 case 变体stringArgument(string:),但实际不存在这个变体,就会抛出你看到的编译错误。
解决方案
有两种可行的处理方式:
- 方案1:保留自动合成逻辑,去掉关联值的
_外部标签,给关联值设置明确的外部参数名,和第二个枚举的写法一致即可。 - 方案2:如果必须保留
_的参数标签写法,手动实现Codable协议的 required 方法,放弃自动合成的逻辑,示例代码如下:
enum ThisEnumDoesNot: Codable { case stringArgument(_ string: String) case intArgument(_ int: Int) enum CodingKeys: String, CodingKey { case stringArgument, intArgument } enum StringArgumentCodingKeys: String, CodingKey { case string // 可自定义编码用的key值 } enum IntArgumentCodingKeys: String, CodingKey { case int // 可自定义编码用的key值 } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) switch self { case .stringArgument(let string): var nestedContainer = container.nestedContainer(keyedBy: StringArgumentCodingKeys.self, forKey: .stringArgument) try nestedContainer.encode(string, forKey: .string) case .intArgument(let int): var nestedContainer = container.nestedContainer(keyedBy: IntArgumentCodingKeys.self, forKey: .intArgument) try nestedContainer.encode(int, forKey: .int) } } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) if let nestedContainer = try? container.nestedContainer(keyedBy: StringArgumentCodingKeys.self, forKey: .stringArgument) { let string = try nestedContainer.decode(String.self, forKey: .string) self = .stringArgument(string) return } if let nestedContainer = try? container.nestedContainer(keyedBy: IntArgumentCodingKeys.self, forKey: .intArgument) { let int = try nestedContainer.decode(Int.self, forKey: .int) self = .intArgument(int) return } throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "无法匹配枚举case")) } }
内容的提问来源于stack exchange,提问作者LLooggaann
相关产品推荐
相关产品推荐

