我们说我有一个班级Car
,其中包含以下属性方案:
@interface Car : NSObject
@property int carID;
@property Driver *driver;
@property NSString *brandName;
...
@end
现在,我有一个Car
个实例的字典,每当我从服务器下载一个新实例时,我都会用carDictionary[@(newCar.carID)] = newCar;
覆盖以保持我的实例更新。唯一的问题是,有时我的实例会被下载,但有些属性没有填写。
当我下载一个新实例时,有没有办法只使用我下载的非零属性覆盖并单独保留nil属性?显然,我可以手动设置每个属性,但是我我不希望每次添加新房产时都要更改此设置。
答案 0 :(得分:2)
在Objective-C中没有内置的方法来执行此操作。也就是说,我认为这就是我接近它的方式。
我首先在Car
上添加一个方法,用新信息更新它:
-(void)updateWithNewCarInfo(Car *)newCar
直接的方法是自己手动复制属性。但是如果你想做一些面向未来的工作,你可以使用Objective-C的内省功能来获取你的类的属性列表,并自己迭代它们。 This question对如何做到这一点有一些指示。但是,您需要实现自己的逻辑,以确定在何时覆盖哪些属性。
答案 1 :(得分:2)
由于此地点的carDictionary
中已经有一个Car对象,而不是大肆替换它,所以写一个Car方法updateWithValuesFromCar:
,然后再接另一辆Car并做你想做的事,然后调用它。
我将从一个属性名称@["carID", "driver", "brandName"]
(依此类推)开始,然后循环使用键值编码来检查每个传入的属性值,并决定是否替换我自己的相应属性值。 / p>
答案 2 :(得分:1)
我们假设您的网络服务电话会收到字典。现在,您希望使用该字典来实例化或更新Car对象,其中更新不会使用字典中的nil数据覆盖现有的有效数据。
假设类中的属性名称与字典中的键名相对应。
这是一种方法:
从carDictionary获取当前词典的现有Car对象:
Car *currentCar = carDictionary[@(newCar.carID)];
如果没有返回汽车,请实例化一个新车:
if (currentCar == nil) {
currentCar = [[Car alloc] init];
}
将下载词典中的所有值分配给汽车实例:
[currentCar setValuesForKeysWithDictionary:yourDownloadedDictionary];
该方法将使用Car实例中的键映射字典中的键。字典键需要与您班级中的键匹配,并且通常值得使用相同的名称,因此您可以使用这种方便的方法。
如果您的Web服务字典中添加了与您的类中的键/属性无关的新密钥,则会引发异常。如果您的网络服务开始提供新密钥,而某些用户的应用程序版本过时,这会破坏您的应用。要解决这个问题..
覆盖- (void)setValue:(id)value forUndefinedKey:(NSString *)key;
所以它什么都不做,除了可能会注意到尝试设置密钥但你的类没有实现该密钥/属性的事实。
然后你就会遇到“不要设置nil值"”的问题。您可以告诉您的班级不要用nil值覆盖现有内容......
覆盖-(void)setValue:forKey
:
-(void)setValue:(id)value forKey:(NSString *)key {
if (value != nil) {
[super setValue:value forKey:key];
} else {
NSLog(@"Not changing %@ because its value is nil.", key);
}
}
在设置课程方面还有一些工作要做,但它可以为您的Web服务扩展其返回的属性集提供进一步的证明。