Dan*_*bbs 6 objective-c nscoding
我有以下实现的类,NSCoding我已经创建了它的几个实例并将它们保存到文件中.
@interface BiscuitTin ()
@property NSString *biscuitType;
@property int numBiscuits;
@end
@implementation BiscuitTin
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
self.biscuitType = [coder decodeObjectForKey:@"biscuitType"];
self.numBiscuits = [coder decodeIntForKey:@"numBiscuits"];
}
return self;
}
- (void)encodeWithCoder:(NSCoder *coder) {
[coder encodeObject:self.biscuitType forKey:@"biscuitType"];
[coder encodeInt:self.numBiscuits forKey:@"numBiscuits"];
}
@end
Run Code Online (Sandbox Code Playgroud)
我现在决定将其表示numBiscuits为float(因为可能有部分吃过的饼干).更新属性类型并且encodeWithCoder工作正常但是当我尝试从文件加载现有实例时,应用程序崩溃,因为它正在尝试解码a int和a float.
有一个很好的方法来处理这个?理想情况下,我可以加载现有int值并将其转换为a float,但我不介意只使用默认值而不是崩溃.
我已经考虑decode在try-catch中包装适用的行,但在我的实际用例中,大约有50个左右的属性正在被编码/解码,并且不必为每个有变化的每个属性进行显式处理类型.
当我自己处理这种情况时(我有几次),我使用 版本控制.换句话说,将版本号与其余编码数据一起编码.
即使您从一开始就没有进行版本控制,这不是真正的问题,您现在可以从版本开始1,只需将缺少version值视为与版本等效0.
怎么样?
将version字段存储在要编码的对象中.使用int或NSInteger用于此字段可能是最好的.
#define CURRENT_VERSION 1
#define MIN_VERSION_WITH_FEATURE_X 1
@implementation BiscuitTin
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
...
int vers = [coder decodeIntForKey:@"version"];
if (vers >= MIN_VERSION_WITH_FEATURE_X) {
// handle feature X. In your case, decoding a `float`
} else {
// handle prior version.
// In your case, decoding an `int` and converting to `float`
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *coder) {
...
[coder encodeInt:CURRENT_VERSION forKey:@"version"];
}
@end
Run Code Online (Sandbox Code Playgroud)
每当您添加一个不向后兼容的新功能时,请增加CURRENT_VERSION,MIN_VERSION_WITH_FEATURE_Y使用新的CURRENT_VERSION整数值添加新常量,并在if语句中添加另一个分支-initWithCoder:.
它有点乱,但我想这是向后兼容的成本.(从好的方面来说,我认为这种技术是相当自我记录的,因此当您几个月或几年后返回时它很容易使用).
在类似的情况下,我更新了代码以将更改的属性保存在新名称下。然后initWithCoder:代码查找新名称。如果不存在,它会在旧名称下查找旧值。
因此,您的代码的第 2 版(属性更改为 a float)将类似于以下内容:
@interface BiscuitTin ()
@property NSString *biscuitType;
@property float numBiscuits;
@end
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
self.biscuitType = [coder decodeObjectForKey:@"biscuitType"];
if ([coder containsValueForKey:@"numBiscuits2"]) {
// Process a version 2 archive
self.numBiscuits = [coder decodeFloatForKey:@"numBiscuits2"];
} else if ([coder containsValueForKey:@"numBiscuits"]) {
// Process a version 1 archive
int oldIntVal = [coder decodeIntForKey:@"numBiscuits"];
self.numBiscuits = oldIntVal;
}
}
return self;
}
- (void)encodeWithCoder:(NSCoder *coder) {
[coder encodeObject:self.biscuitType forKey:@"biscuitType"];
// [coder encodeInt:self.numBiscuits forKey:@"numBiscuits"]; // obsolete version
[coder encodeFloat:self.numBiscuits forKey:@"numBiscuits2"]; // new key name
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
300 次 |
| 最近记录: |