我正在从缓存的序列化中解码自定义对象。我已经对该对象进行了版本化,因为它已被编码,如果序列化版本是旧版本,我想把它扔掉。我的印象是我可以从我的initWithCoder:方法返回nil,一切都会好的。但是这会引发错误。
编辑 - 根据NSObject的+版本:文档“版本号适用于NSArchiver / NSUnarchiver,但不适用于NSKeyedArchiver / NSKeyedUnarchiver。键控归档器不编码类版本号。”我正在使用一个键控归档器,因此这种方法无济于事。
我使用自己的嵌入版本号,而不是NSObject版本+ NSCoder的versionForClassName:。这是怎么回事?如果Class版本不匹配,NSCoder会自动中止尝试解码,还是需要手动检查。
我目前正在这样做:
- (id)initWithCoder:(NSCoder *)coder {
if (![coder containsValueForKey:@"Class.User.version"]) {
// Version information missing
self = nil;
return nil;
}
NSInteger modelVersion = [coder decodeIntForKey:@"Class.User.version"];
if (modelVersion < USER_MODEL_VERSION) {
// Old user model, discard
self = nil;
return nil;
}
...
}
我在尝试解码旧版本时遇到此错误
-[__NSPlaceholderDictionary initWithObjects:forKeys:]: number of objects (0) not equal to number of keys (46)'
这一切看起来很奇怪,因为初始化程序可能由于多种原因而失败,并且在这种情况下模式将返回nil,那么这是否真的会使解码器崩溃?
编辑 - 每Apple's documentation听起来我正在以正确的方式接近这一点。然而,似乎没有一种机制可以在对象陈旧且过时时完全中止解码。我没有或想要从旧对象升级路径,所以我该怎么办?
答案 0 :(得分:1)
而不是将self
设置为nil
,将您解码的所有单个属性设置为nil
,然后返回self
。所以,写下这个:
if (modelVersion < USER_MODEL_VERSION) {
// Old user model, discard
object1 = nil;
object2 = nil;
...
object46 = nil;
}
return self;
这实际上将返回正确类型的对象和所有属性,但所有属性都将为nil
。