CoreData使用Transformable属性存储自定义类时保存失败如何解决?
CoreData Transformable属性存储自定义类报错解决方案
错误原因
你遇到的报错是因为默认的NSSecureUnarchiveFromData转换器未配置自定义类的白名单,同时原有解码代码不符合NSSecureCoding的安全要求导致的。
修复步骤
1. 修正自定义类的解码逻辑
NSSecureCoding要求解码时必须明确指定待解码对象的类型,不能直接使用无类型的decodeObject(forKey:)方法,修正后的EntityData代码如下:
import UIKit import CoreData public class EntityData: NSObject, NSSecureCoding { public static var supportsSecureCoding: Bool { true } public func encode(with coder: NSCoder) { coder.encode(self.name, forKey: "name") } public required init?(coder: NSCoder) { // 明确指定解码类型为NSString,符合安全编码要求 self.name = coder.decodeObject(of: NSString.self, forKey: "name") as? String } var name: String? init(name: String?) { self.name = name } }
2. 自定义安全解码转换器
自定义继承自NSSecureUnarchiveFromDataTransformer的转换器,将EntityData加入允许解档的白名单:
@objc(EntityDataTransformer) class EntityDataTransformer: NSSecureUnarchiveFromDataTransformer { static let name = NSValueTransformerName(rawValue: "EntityDataTransformer") // 配置允许解档的顶级类 override static var allowedTopLevelClasses: [AnyClass] { return [EntityData.self] } // 注册转换器,需在CoreData初始化前调用 public static func register() { let transformer = EntityDataTransformer() ValueTransformer.setValueTransformer(transformer, forName: name) } }
3. 注册转换器并修改CoreData配置
- 在App启动阶段注册转换器,比如在
AppDelegate的application(_:didFinishLaunchingWithOptions:)方法中添加注册代码:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { EntityDataTransformer.register() return true }
- 打开CoreData模型编辑器,找到对应实体的
data属性配置:
- Transformer 字段填写转换器名称:
EntityDataTransformer - Class 字段填写自定义类的完整名称,格式为
你的项目模块名.EntityData(单模块项目可直接填EntityData,多模块项目必须带上模块名)
4. 验证修复
卸载模拟器/设备上的原有App(清除旧的CoreData存储缓存),重新运行项目即可正常存储自定义类属性。
内容的提问来源于stack exchange,提问作者Aykhan Hagverdili
相关产品推荐
相关产品推荐

