Xcode NSUserDefaults和序列化数据
我对我们应用程序中的数据持久化方法有问题。决定将NSUserDefaults与NSCoding兼容的数据模型一起使用,由于我们应用程序的规模,我不同意这一点 我看到的问题是,当数据模型更改时,任何反序列化的尝试都会导致崩溃。必须卸载并重新安装应用程序才能重新序列化 场景:Xcode NSUserDefaults和序列化数据,xcode,swift3,nsuserdefaults,nscoding,Xcode,Swift3,Nsuserdefaults,Nscoding,我对我们应用程序中的数据持久化方法有问题。决定将NSUserDefaults与NSCoding兼容的数据模型一起使用,由于我们应用程序的规模,我不同意这一点 我看到的问题是,当数据模型更改时,任何反序列化的尝试都会导致崩溃。必须卸载并重新安装应用程序才能重新序列化 场景: class Contact: NSCoding { var name var address var userId } ... // NSCoding compliance happens next.
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
}
... // NSCoding compliance happens next. This object gets serialized.
有人认为联系人需要更多的东西:
class Contact: NSCoding {
var name
var address
var userId
var phoneNumber
var emailAddress
}
尝试反序列化联系人对象,即使编码和解码的NSCoding符合性已更新为加载和反序列化,也会导致
致命错误:在展开可选值时意外发现nil
CoreDataManager.unarchiveUser
Worker.init
所以,我的问题是,当运行具有不同模式的应用程序更新版本时,我们如何避免发生此崩溃???您崩溃的原因是
解码对象(forKey:)
(因为对象编码时该键在类中不存在)。此方法返回nil
代码>强制展开#1的结果
的行上崩溃代码>,大约有95%的可能性代码>是导致崩溃的直接原因。如果错误消息中提到展开可选文件,则有100%的可能性
decodeObject(forKey:)
方法的文档说明它可能返回nil
。在您的情况下,如果您从类的早期版本升级,并且您正在解码刚刚添加的密钥,那么这种情况肯定会发生
您的代码需要认识到新属性可能没有值。最简单的修复方法是将替换为代码>与相同?
。然后,您将获得新属性的nil
值。对于非可选的属性,可以添加类似于??“默认值”
结束
您还可以使用containsValue(forKey:)
方法在尝试解码密钥之前检查值是否存在。您崩溃的原因是
您正试图对一个不存在的键进行解码对象(forKey:)
(因为对象编码时该键在类中不存在)。此方法返回nil
您正在使用代码>强制展开#1的结果
根据经验,如果您的Swift代码在包含的行上崩溃代码>,大约有95%的可能性代码>是导致崩溃的直接原因。如果错误消息中提到展开可选文件,则有100%的可能性
decodeObject(forKey:)
方法的文档说明它可能返回nil
。在您的情况下,如果您从类的早期版本升级,并且您正在解码刚刚添加的密钥,那么这种情况肯定会发生
您的代码需要认识到新属性可能没有值。最简单的修复方法是将替换为代码>与相同?
。然后,您将获得新属性的nil
值。对于非可选的属性,可以添加类似于??“默认值”
结束
您还可以使用containsValue(forKey:)
方法在尝试解码密钥之前检查值是否存在。您是否使用核心数据?你说你没有,但你正在使用一个名为CoreDataManager
的类。你需要发布NSCoding编码部分。我不认为他在使用核心数据,看起来他在将其保存到UserDefaults。UserDefaults有一个名为data(forKey:)
的方法你在使用核心数据吗?你说你没有,但你正在使用一个名为CoreDataManager
的类。你需要发布NSCoding编码部分。我不认为他在使用核心数据,看起来他正在将其保存到userdefaultsBTW。UserDefaults有一个名为data(forKey:)
的方法,如果decoder.containsValue(forKey:“mobilePhoneNumber”)有帮助,但是让officePhoneNumber:String=decoder.decodeObject(forKey:officePhoneNumber)作为?一串“”如果你关心你的类是否有有效的数据,那就真的更好了。这里真正的解决方案是停止滥用UserDefaults
,使用真正的存储系统。我完全同意你@JonShier的观点。我正在推动系统使用更好的东西。该团队说CoreData太多了,但NSUserDefaults则是相反的极端。我在想,围绕sqlite3的包装器,比如FMDB,将是一个很好的快乐媒介。也许他们会喜欢Realm?这取决于你需要储存什么。只有在需要性能时,我才会回退到SQLite。更高级别的东西可能会更好。领域?我没听说过。谢谢你的建议。如果decoder.containsValue(forKey:“mobilePhoneNumber”)有帮助,但是让officePhoneNumber:String=decoder.decodeObject(forKey:“officePhoneNumber”)作为?一串“”如果你关心你的类是否有有效的数据,那就真的更好了。这里真正的解决方案是停止滥用UserDefaults
,使用真正的存储系统。我完全同意你@JonShier的观点。我正在推动系统使用更好的东西。该团队说CoreData太多了,但NSUserDefaults则是相反的极端。我在想围绕sqlite3的包装器,比如FMDB,将是一个不错的选择