从NSCoder解码对象时,中止的最佳方法是什么?

时间:2011-07-09 00:08:35

标签: iphone objective-c serialization nscoding

我正在从缓存的序列化中解码自定义对象。我已经对该对象进行了版本化,因为它已被编码,如果序列化版本是旧版本,我想把它扔掉。我的印象是我可以从我的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听起来我正在以正确的方式接近这一点。然而,似乎没有一种机制可以在对象陈旧且过时时完全中止解码。我没有或想要从旧对象升级路径,所以我该怎么办?

1 个答案:

答案 0 :(得分:1)

而不是将self设置为nil,将您解码的所有单个属性设置为nil,然后返回self。所以,写下这个:

if (modelVersion < USER_MODEL_VERSION) {
    // Old user model, discard
    object1 = nil;
    object2 = nil;
    ...
    object46 = nil;
}
return self;

这实际上将返回正确类型的对象和所有属性,但所有属性都将为nil