KVC,KVO

NSKeyValueCoding 为 NSObject的category 所以所有NSObject的子类都具备下列方法;


设置一个对象属性的值

- (void)setValue:(id)value forKey:(NSString *)key;

获取一个对象属性的值

- (id)valueForKey:(NSString *)key;


可使用带有path的方法以点运算符组成的路径的形势完成KVO的获取与设置如:

    [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"];


由此可见path的语法即是调用相应的getter和setter方法,如果方法没有找到且accessInstanceVariablesDirectly方法返回YES那么按顺便查找_+ , _is+, is+。开头的成员。如果仍然没有找到将会调用 valueForUndefinedKey方法


如果作用的对象是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"];





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值