CoreData存储UIBezierPath出现NSKeyedUnarchiveFromData警告如何解决
UIBezierPath序列化存入CoreData最佳实践
警告根因
你遇到的弃用警告是苹果在iOS 12+之后推进NSSecureCoding替代原有不安全解档机制导致的:一是你当前编码方法里requiringSecureCoding设为了false,二是默认Transformable类型使用的NSKeyedUnarchiveFromDataTransformer已被标记为弃用,后续系统版本会移除相关实现。
方案1:基于Data类型字段适配(无需修改现有存储结构)
直接修改你当前的编解码方法,开启安全编码即可,UIBezierPath原生支持NSSecureCoding协议,适配成本极低:
func bezierToData(path: UIBezierPath) -> Data? { do { // 开启安全编码,匹配苹果最新规范 return try NSKeyedArchiver.archivedData(withRootObject: path, requiringSecureCoding: true) } catch { print("UIBezierPath编码失败: \(error)") return nil } } func dataToBezier(src: Data) -> UIBezierPath? { do { // 去掉强制解包,异常场景返回空即可 return try NSKeyedUnarchiver.unarchivedObject(ofClass: UIBezierPath.self, from: src) } catch { print("UIBezierPath解码失败: \(error)") return nil } }
该方案完全兼容你之前已经存入CoreData的历史数据,不需要做任何迁移操作。
方案2:正确配置Transformable类型字段(无需手动编解码)
如果不想每次手动调用转换方法,可以用Transformable类型,只要自定义安全解档转换器即可,步骤如下:
- 打开CoreData的xcdatamodeld模型文件,将对应存储字段的Type改为
Transformable - 选中该字段,打开右侧Data Model Inspector:
Custom Class栏填UIBezierPath,Transformer栏填你自定义的转换器名称(比如BezierPathTransformer) - 实现自定义转换器类:
@objc(BezierPathTransformer) class BezierPathTransformer: NSSecureUnarchiveFromDataTransformer { // 指定允许解档的类类型 override class var allowedTopLevelClasses: [AnyClass] { [UIBezierPath.self] } // 注册转换器,需要在CoreData初始化前调用 static func register() { let transformer = BezierPathTransformer() ValueTransformer.setValueTransformer(transformer, forName: NSValueTransformerName(rawValue: "BezierPathTransformer")) } }
- 在App启动阶段、CoreData栈初始化之前调用注册方法,比如在
AppDelegate的application(_:didFinishLaunchingWithOptions:)里调用BezierPathTransformer.register()
配置完成后你可以直接把字段当做UIBezierPath?类型使用,CoreData会自动完成序列化/反序列化操作。
注意事项
- 两种方案均符合苹果当前API规范,不存在后续版本兼容性问题
- 开启安全编码后会校验解档类的类型,避免恶意数据导致的安全风险,是苹果推荐的实现方式
- 两种方案均兼容历史存量数据,不需要额外做数据迁移处理
内容的提问来源于stack exchange,提问作者Dan Donaldson
相关产品推荐
相关产品推荐

