1、What is Key-Value coding ?
KVC : NSKeyValueCoding protocol的简称(也称Key-Value coding),该协议定义了应用通过变量名(key)存取对象中的属性的机制。Key-Value coding用于key-value observing、Cocoa bindings、Core Data以及是应用支持AppleScript(苹果的一种脚本语言)。在程序中实现key-value coding是一种重要的设计模式,可以大大简化程序代码。
Using Key-Value Coding to simplify code(简化代码) :
下面我们来看看几个例子,就明白了KVO的用法和好处了,假设这样个类叫做People, 有以下两个属性:
@property (nonatomic, strong) NSString *name;
@property (nonatomic, strong) NSNumber *age;
**场景1、**apple 官网的一个例子,当我们需要统计很多People的时候,每一行是一个人的实例,并且有2列属性,name, age, 这时候我们可以会这样做,
- (id)tableView:(NSTableView *)tableview
objectValueForTableColumn:(id)column row:(NSInteger)row
{
People *people = [peoleArray objectAtIndex:row];
if ([[column identifier] isEqualToString:@"name"]) {
return [people name];
}
if ([[column identifier] isEqualToString:@"age"]) {
return [people age];
}
// And so on.
}
同样我们也可以用KVC,帮助我们化简这些if, 因为name, age其实都是property, 我们可以直接通过key来访问,所以整理过后是
People *people = [peopleArray objectAtIndex: row];
return [people valueForKey: [column identifier]];
可以看到使用MVC设计模式之后****代码量大大减小**。**
场景2、我们向server请求数据,server的某个API会返回我们json格式一个数组,里面包含这样dict{name:xx, age:xx}这样的数据, 我们希望用这些dict数据构造出我们的people来,通常我们的做法是:为我们People类写一个static factory方法专门用来处理dict来, 把dict里面的数据取出来, 然后创建个空的People对象,然后依次设置property。如果类中的property比较多,我们就要写很多的赋值代码,这无疑是重复且令人厌烦的工作,这时就可以使用KVC来进行简化了:
-(id) initWithDictionary:(NSMutableDictionary*) jsonObject
{
if((self = [super init]))
{
[self init];
[self setValuesForKeysWithDictionary: jsonObject];
}
return self;
}
这样就能将字典中所有键所对应的值付给与该键相同名字的property了。但是新的问题产生了,**如果json里面的某些key和object的property名字不一样呢,或者有些server返回的字段是objc保留字如”id”, “description”等,** 我们也希望也map dict to object, 这时候我们就需要用上setValue:forUndefinedKey, 因为如果我们不处理这些Undefined Key,还是用setValuesForKeysWithDictionary就会抛出异常。
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if([key isEqualToString:@“某个键"])
self.name = value;
if([key isEqualToString:@“某个键"])
self.age = value;
else
[super setValue:value forKey:key];
}
**该方法先将键和object的property名字不同的情况单独处理,**再将字典中所有键所对应的值付给与该键相同名字的property了
场景3、People类有一个name属性,该属性是Name类的对象(Name类包含两个属性:NSString* firstName , NSString* lastName),那么如何通过KVC设置name的值呢:
[aPeople setValue: @“张” ForKeyPath: @“name.firstName”];
[aPeople setValue: @“三” ForKeyPath: @“name.lastName”];