Swift中结构体集合编码问题:NSKeyedUnarchiver弃用后的解决方案
结构体集合的归档/解归档替代方案(iOS)
你遇到的问题核心在于:NSKeyedUnarchiver的新API基于Objective-C的NSCoding协议,仅支持继承自NSObject的类类型,而Swift结构体属于值类型,无法遵循这类类协议。
最适配Swift值类型的解决方案是使用Swift原生的Codable协议,它完美支持结构体、枚举等值类型,编码解码逻辑更简洁,无需依赖Objective-C runtime。
步骤1:让结构体遵循Codable
给你的Cloud结构体添加Codable协议(如果结构体的所有属性都是默认支持Codable的类型,比如String、Int、Bool等,无需额外实现编码解码方法):
struct Cloud: Codable { // 你的结构体属性示例 var identifier: String var storageSize: Int // 其他自定义属性... }
步骤2:归档(编码)结构体集合到文件
替换原有的归档逻辑,用JSONEncoder或PropertyListEncoder将集合编码为Data后写入文件:
// 示例:要归档的Cloud集合 let cloudSet: Set<Cloud> = [ Cloud(identifier: "cloud_01", storageSize: 512), Cloud(identifier: "cloud_02", storageSize: 1024) ] // 获取文件存储路径(示例用Documents目录) guard let documentsDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { fatalError("无法获取Documents目录") } let archivePath = URL(fileURLWithPath: documentsDir).appendingPathComponent("clouds.archive").path // 执行归档操作 do { // 可替换为PropertyListEncoder()生成更紧凑的二进制格式 let encodedData = try JSONEncoder().encode(cloudSet) try encodedData.write(to: URL(fileURLWithPath: archivePath)) } catch { print("归档失败:\(error.localizedDescription)") }
步骤3:解归档(解码)从文件读取集合
替换你原来的unarchiveObject(withFile:)代码,用JSONDecoder读取并解码:
// 读取相同的文件路径 guard let documentsDir = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true).first else { fatalError("无法获取Documents目录") } let archivePath = URL(fileURLWithPath: documentsDir).appendingPathComponent("clouds.archive").path // 执行解归档操作 do { let archivedData = try Data(contentsOf: URL(fileURLWithPath: archivePath)) // 解码为Set<Cloud>类型 let output = try JSONDecoder().decode(Set<Cloud>.self, from: archivedData) // 此处可使用解归档后的output集合 print("解归档成功:\(output)") } catch { print("解归档失败:\(error.localizedDescription)") }
补充说明
- 如果必须和旧的
NSKeyedArchiver归档格式兼容,只能将Cloud改为继承自NSObject的类并实现NSCoding协议,但这会违背使用结构体的设计初衷。 Codable支持JSON和Plist两种编码格式:JSONEncoder生成的文件可读性更强,PropertyListEncoder生成的文件更紧凑,可根据需求选择。
内容的提问来源于stack exchange,提问作者Fabrizio Bartolomucci
相关产品推荐
相关产品推荐

