遵循Codable的Swift结构体属性使用@available(unavailable)报错如何解决
问题原因
@available(*, unavailable)标记表示该属性在所有平台均不可用,任何直接访问该属性的代码都会触发编译报错。
当结构体遵循Codable协议时,Swift编译器会自动生成编解码实现,自动生成的代码会直接访问所有存储属性,包括你标记为不可用的oldProperty,由此触发编译错误。
当结构体不遵循Codable时,只要你自己的业务代码没有访问oldProperty,就不会触发访问校验,因此可以正常编译。
解决方案
你需要手动实现Codable协议的编解码逻辑,完全绕过对oldProperty的访问即可解决问题,同时可以根据是否需要兼容旧数据字段选择实现方式:
方案1:不需要兼容旧的oldProperty字段
将不可用的属性改为计算属性,避免被自动合成的Codable逻辑识别为存储属性,同时手动声明编码键过滤旧属性即可:
struct SampleData: Codable { @available(*, unavailable, renamed: "newProperty") var oldProperty: String { fatalError("oldProperty 已废弃,请使用 newProperty") } let newProperty: String enum CodingKeys: String, CodingKey { case newProperty } }
这种场景下编译器不会生成访问oldProperty的代码,编译可以正常通过。
方案2:需要兼容包含oldProperty字段的旧数据
手动实现完整的编解码逻辑,处理旧字段的兼容转换即可:
struct SampleData: Codable { @available(*, unavailable, renamed: "newProperty") var oldProperty: String { fatalError("oldProperty 已废弃,请使用 newProperty") } let newProperty: String enum CodingKeys: String, CodingKey { case newProperty case oldProperty } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) // 优先读新字段, fallback 到旧字段 self.newProperty = try container.decodeIfPresent(String.self, forKey: .newProperty) ?? try container.decode(String.self, forKey: .oldProperty) } func encode(to encoder: Encoder) throws { var container = encoder.container(keyedBy: CodingKeys.self) try container.encode(newProperty, forKey: .newProperty) } }
内容的提问来源于stack exchange,提问作者Kazunori Takaishi
相关产品推荐
相关产品推荐

