4

我正在从缓存的序列化中解码自定义对象。我已经对对象进行了版本化++,因为它被编码了,如果序列化版本是旧版本,我想把它扔掉。我的印象是我可以从我的 initWithCoder: 方法返回 nil,一切都会好起来的。不过,这会引发错误。

编辑- 根据 NSObject 的 +version:文档“版本号适用于 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 的文档,听起来我正在以正确的方式处理这个问题。然而,如果一个对象是旧的和过时的,似乎没有一种完全中止解码的机制。我没有或不想要旧对象的升级路径,我该怎么办?

4

1 回答 1

1

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

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

这将本质上返回一个正确类型的对象和所有,但所有属性都是nil.

于 2011-07-09T02:28:13.513 回答