我工作的Update
我的OS X
应用程序,它最初是写在Obj-C
。
更新已被写入Swift
我遇到了一个用户默认值处理的奇怪问题。(因为用户首选项不能在更新中更改)
所有本机类型(例如Bool, String
)的用户首选项都可以正常工作,但是NSCoding
符合标准的Class不能deserialse / Unarchive
。它给出了一个错误:
Error :[NSKeyedUnarchiver decodeObjectForKey:]: cannot decode object of class (KSPerson) for key (NS.objects); the class may be defined in source code or a library that is not linked
我进行了以下尝试,但仍然无法找出解决方案
Swift
其Person
代替KSPerson
)。但是更改类名(返回KSPerson
)并不能解决问题Objective C
更像我也尝试过@objc
这是代码
let UD = NSUserDefaults.standardUserDefaults()
func serialize() {
// Info: personList: [KSPerson]
let encodedObject: NSData = NSKeyedArchiver.archivedDataWithRootObject(personList)
UD.setObject(encodedObject, forKey: "key1")
print("Serialization complete")
}
func deserialise() {
let encodedObject: NSData = UD.objectForKey("key1") as! NSData
let personList: [KSUrlObject] = NSKeyedUnarchiver.unarchiveObjectWithData(encodedObject) as! [KSPerson]
for person in personList {
print(person)
}
注:
我创建了一个duplicate copy
的Objective C
代码,并deserialised完美(什么是由原件连载)。
出乎我的意料。当我重新命名类KSPerson
来JSPerson
在duplicate copy
上面看到它给我确切的同样的错误
所以一件事很清楚。您需要具有与UnarchiveNSCoding
兼容的相同的类名objects
。但这显然不足以Swift
Swift类包括其模块名称。Objective-C类没有。因此,当您取消归档Objective-C类“ KSPerson”时,Swift将遍历所有类并找到“ mygreatapp.KSPerson”,并得出结论,它们不匹配。
您需要告诉取消归档的人如何将归档名称映射到模块的类名称。您可以使用以下命令集中执行此操作setClass(_:forClassName:)
:
NSKeyedUnarchiver.setClass(KSPerson.self, forClassName: "KSPerson")
这是全局注册,适用于所有不覆盖它的未归档程序。当然,您可以为同一类注册多个名称以进行存档。例如:
NSKeyedUnarchiver.setClass(KSPerson.self, forClassName: "KSPerson")
NSKeyedUnarchiver.setClass(KSPerson.self, forClassName: "mygreatapp.Person")
NSKeyedUnarchiver.setClass(KSPerson.self, forClassName: "TheOldPersonClassName")
编写Swift档案时,默认情况下它将包含模块名称。这意味着,如果您曾经更改模块名称(或在一个模块中归档而在另一个模块中取消归档),则将无法取消归档数据。这样做有一些好处(可以防止意外将其归档为错误的类型),但是在许多情况下,您可能不希望这样做。如果没有,您可以通过在另一个方向注册映射来覆盖它:
NSKeyedArchiver.setClassName("KSPerson", forClass:KSPerson.self)
这仅影响注册后归档的类。它不会修改现有档案。
这仍然很脆弱。unarchiveObjectWithData:
遇到问题时会引发ObjC异常,而Swift无法捕获。您将因坏数据而崩溃。您可以避免使用-decodeObjectForKey
而不是+unarchiveObjectWithData
:
let encodedObject: NSData = UD.objectForKey("key1") as? NSData ?? NSData()
let unarchiver = NSKeyedUnarchiver(forReadingWithData: encodedObject)
let personList : [KSPerson] = unarchiver.decodeObjectForKey(NSKeyedArchiveRootObjectKey) as? [KSPerson] ?? []
[]
如果有问题而不是崩溃,则返回此值。它仍然尊重全局类名注册。
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句