Swift中Codable结构体无法编码ObjectIdentifier问题求助
解决ObjectIdentifier的Codable编码问题
问题根源很明确:Swift的ObjectIdentifier类型并没有默认遵循Codable协议,所以当你的ProjectBlock结构体包含这类属性时,JSON编码器无法自动处理它的序列化逻辑,直接导致编码失败。
要解决这个问题,你需要给ObjectIdentifier扩展Codable协议,自定义它的编码和解码逻辑——把它转换成能被JSON识别的基础类型(比如UInt64或者字符串)。
步骤1:给ObjectIdentifier添加Codable扩展
extension ObjectIdentifier: Codable { public func encode(to encoder: Encoder) throws { var container = encoder.singleValueContainer() // 把ObjectIdentifier转换成UInt64类型编码 try container.encode(self.uintValue) } public init(from decoder: Decoder) throws { let container = try decoder.singleValueContainer() let uintValue = try container.decode(UInt64.self) // 通过UInt64值初始化ObjectIdentifier self.init(uintValue: uintValue) } }
这里利用了ObjectIdentifier的uintValue属性(它是一个唯一标识对象的64位无符号整数),把它转换成JSON支持的数值类型完成编码,解码时再通过这个数值还原ObjectIdentifier。
步骤2:恢复ProjectBlock中的ObjectIdentifier属性
现在你可以把之前注释掉的属性和CodingKeys恢复,正常使用了:
struct ProjectBlock : Codable { var comps: [ObjectIdentifier]? var gitpaths: [ObjectIdentifier]? var inProject: ObjectIdentifier? var selectionThreads: [ObjectIdentifier]? var name: String var exportObjID: ObjectIdentifier init(block: Blocks) { name = block.name! exportObjID = block.id inProject = block.inProject!.id } enum CodingKeys: String, CodingKey { case comps case gitpaths case inProject case selectionThreads case exportObjID case name } }
补充说明
- 如果你更倾向于用字符串形式存储
ObjectIdentifier,也可以把编码逻辑改成try container.encode(self.description),解码时先解码字符串再通过ObjectIdentifier(string:)初始化,但这种方式不如用uintValue高效。 - 注意:
ObjectIdentifier是基于对象内存地址生成的,跨进程或重启App后,同一个逻辑对象的内存地址会变化,对应的ObjectIdentifier也会不同。如果你的需求是跨环境恢复实体关系,可能需要改用自定义的唯一标识符(比如UUID、数据库主键),而不是依赖ObjectIdentifier。
内容的提问来源于stack exchange,提问作者Dan Donaldson
相关产品推荐
相关产品推荐

