我的应用程序中的数据持久性方法存在问题。决定将NSUserDefaults与NSCoding兼容的数据模型一起使用,由于我们的应用程序的规模,我不同意这一点。
我看到的问题是数据模型发生变化时,任何反序列化的尝试都会导致崩溃。必须卸载并重新安装该应用才能重新序列化。
方案:
这种情况正在发生,因为数据已使用与现在尝试反序列化的模型不同的模型进行序列化。
示例:
class Contact: NSCoding {
var name
var address
var userId
}
... // NSCoding compliance happens next. This object gets serialized.
有人认为联系人需要更多东西:
class Contact: NSCoding {
var name
var address
var userId
var phoneNumber
var emailAddress
}
尝试对Contact对象进行反序列化,即使编码和解码的NSCoding合规性已更新为加载和反序列化,也会导致
致命错误:在解包可选值时意外发现nil
CoreDataManager.unarchiveUser
Worker.init
所以,我的问题是,在运行具有不同架构的应用程序的更新版本时,我们怎么可能避免发生这种崩溃?
答案 0 :(得分:4)
你崩溃是因为,
decodeObject(forKey:)
关于不存在的密钥(因为在对象编码时它不存在于类中)。此方法返回nil
。!
强制解包#1的结果。根据经验,如果您的Swift代码在包含!
的行上崩溃,则!
导致崩溃的可能性大约为95%。如果错误消息提到展开可选项,那么这是100%的可能性。
decodeObject(forKey:)
方法的文档说明它可能会返回nil
。在您的情况下,如果您从该类的先前版本升级并且您正在解码刚刚添加的密钥,则可以确保这种情况发生。
您的代码需要认识到新属性可能没有值。最简单的解决方法是将as!
替换为as?
。然后,您将获得新属性的nil
值。对于非可选属性,您可以在最后添加?? "default value"
之类的内容。
在尝试解码密钥之前,您还可以使用containsValue(forKey:)
方法检查值是否存在。