Core Data中questionsCD.questions?.questionList赋值失败 读取时返回nil
故障原因&解决方案
核心故障根因
- 新建的
QuestionCD实例的questions属性默认是nil,你直接对questionsCD.questions?.questionList赋值属于对可选链的nil节点赋值,赋值操作会直接被忽略,没有任何效果。 - 嵌套自定义类
QuestionList未实现NSSecureCoding协议,NSSecureCoding解码时无法识别该类的实例,导致解码失败返回nil。 QuestionsValueTransformer的允许顶级类配置不全,缺少解码所需的NSArray和QuestionList类声明。- 若未在Core Data初始化前注册
QuestionsValueTransformer,Core Data无法识别转换器,会直接丢弃对应属性值。
修复步骤
1. 修改保存逻辑,初始化QuestionsNSSecureCoding实例
将saveSelectedQuestion函数中的赋值代码替换为:
// 先创建QuestionsNSSecureCoding实例,再赋值给questions属性 questionsCD.questions = QuestionsNSSecureCoding(questions: questions)
2. 给QuestionList实现NSSecureCoding协议
修改QuestionList类代码:
class QuestionList: Codable, Identifiable, NSSecureCoding { public static var supportsSecureCoding: Bool = true var id: String init(id: String) { self.id = id } public func encode(with coder: NSCoder) { coder.encode(id as NSString, forKey: "id") } required public init?(coder: NSCoder) { guard let id = coder.decodeObject(of: NSString.self, forKey: "id") as? String else { return nil } self.id = id } }
3. 补充QuestionsValueTransformer的允许类列表
修改allowedTopLevelClasses属性:
override static var allowedTopLevelClasses: [AnyClass] { return [QuestionsNSSecureCoding.self, NSArray.self, QuestionList.self] }
4. 确保提前注册转换器
在App启动阶段、Core Data栈初始化前调用注册方法,例如下放在AppDelegate的didFinishLaunchingWithOptions方法中:
QuestionsValueTransformer.register()
可选优化
可以优化QuestionsNSSecureCoding的解码逻辑,提升兼容性:
required public init?(coder: NSCoder) { guard let list = coder.decodeArrayOfObjects(of: [QuestionList.self], forKey: "questionList") else { questionList = [] return } questionList = list }
内容的提问来源于stack exchange,提问作者Ufuk Köşker
相关产品推荐
相关产品推荐

