NSKeyValueCoding 为 NSObject的category 所以所有NSObject的子类都具备下列方法;
设置一个对象属性的值
- (void)setValue:(id)value forKey:(NSString *)key;
获取一个对象属性的值
- (id)valueForKey:(NSString *)key;
[self setValue:@"jack" forKeyPath:@"person.name"];
[self valueForKeyPath:@"person.name"]
当设置或获取的key不存在时会调用相应的undefined方法,可重写此方法使其完成正确的操作
当value为Nil时,如果被设置的属性不是对象时
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"ErrorName"]) {
self.name = value;
return;
}
[super setValue:value forUndefinedKey:key];
}
- (id)valueForUndefinedKey:(NSString *)key
{
if ([key isEqualToString:@"ErrorName"]) {
return self.name;
}
return [super valueForUndefinedKey:key];
}
- (void)setNilValueForKey:(NSString *)key
{
if ([key isEqualToString:@"number"]) {
self.number = 0;
return;
}
[super setNilValueForKey:key];
}
如果被作用于的对象是NSArray那么将产生一对多的结果
以下相当于调用NSArray中每一个元素的length方法,并将每一个元素的length返回的结果组合成新的NSArray返回
self.arr = @[@"a", @"aa", @"aaa", @"aaaa"];
NSArray *lengthArray = [self.arr valueForKeyPath:@"length"];
以下相当于调用NSArray中的每一个元素的setNumber方法,并将value做为参数传入
[self setValue:@1 forKeyPath:@"arr.number"];
如果作用的对象是NSArray还可以使用复合条件
调用NSArray中每一个元素的floatValue方法,并将返回的所有值求平均数
[self.arr valueForKeyPath:@"@sum.floatValue"]
另外还有 @max @min @avg 可以使用,要求点后面指定的方法返回的必需是可计算值
@distinctUnionOfObjects 可以对返回的多个元素做去重操作
需要注意的是使用@特性其后必需有一个点即操作的方法名,如果相对元素本身操作可以使用self
self.arr = @[@"a", @"b", @"a", @"c"];
[self.arr valueForKeyPath:@"@distinctUnionOfObjects.self"];
了解了KVC的机制后就可以利用这点做一些另类的事,比如,直接设置某个类的私有成员变量的值,即使这个变量没有提供使用对外可见的方法,只要已知变量名就可以通过KVC修改,比如修改UITextFiled的占位符字体颜色。
[filed setValue:[UIColor blackColor] forKeyPath:@"_placeholderLabel.textColor"];