在开发中,我们有时候需要求改系统控件里面某个属性,但该属性未必是开放的。那么,我们会想各种办法来完成。比如
UITextField中placeholder的字体颜色。实现方法也很多,比如在用label啊,重写啊这些。我以前也经常这样做。
但是KVC就可以很简单的解决这个问题。
[self.textField setValue:[UIColor redColor] forKeyPath:@"_placeholderLabel.textColor"];
在UITextField中placeholder字体颜色是私有属性,无法直接获取并修改,那么我们就可以使用KVC来实现。
[self.textField valueForKeyPath:@"_placeholderLabel.textColor"];
获取它的值!
总结:KVC可以获取和设置属性(包括该object的私有属性)!!!
赋值的实现过程,
1.查找是否有相关的方法set
2.当没有相关方法的时候判断是否可以直接方法成员变量。- (BOOL)accessInstanceVariablesDirectly;
3.如果是NO,则抛出异常。
4.如果为YES,继续找相关变量_
5.如果方法和成员都不存在,则抛出异常。
取值的实现过程与赋值相似,就不做说明。
那么通过这里,我们也就知道,当你在赋值与取值的时候,使用的是不存在的key,就会抛出异常,当你没有实现异常方法的时候,就会出现闪退的情况!!!所以,我们最好添加上处理方法。
#pragma mark 赋值
//对非对象类型,值不能为空
- (void)setNilValueForKey:(NSString *)key{
NSLog(@"%@ 值不能为空", key);
}
// 当key不存在的时候调用次方法
- (void)setValue:(id)value forUndefinedKey:(NSString *)key{
NSLog(@"%@ key不存在", key);
}
#pragma mark 取值
- (id)valueForUndefinedKey:(NSString *)key{
NSLog(@"key=%@ 不存在", key);
return nil;
}
这里顺带一句。不是有一个万能储存容器么?其实就是这个异常帮忙处理的。
新建一个可变字典。
当抛出异常是,把key和value对应键值储存在字典。也就成了所说的万能储存容器!!!!
下面谈谈KVC的其他用法。
1.关于字典的一次性赋取值
ZPPerson *p = [ZPPerson new];
///一次性赋值
NSDictionary *dic = @{@"name": @"Tom", @"age":@"18", @"nick":@"壮壮", @"accontId":@"123871623871263", @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
NSLog(@"name = %@ age = %d nick = %@ accountId = %@ sex = %@", p.name, p.age, p.nick, p.accontId, p.sex);
///一次性取值
NSArray *ary = @[@"name", @"age", @"nick", @"accontId", @"sex"];
NSDictionary *dict = [p dictionaryWithValuesForKeys:ary];
NSLog(@"dict:%@", dict);
在开发中其实挺好用的,根据接口文档,定义model中的成员,然后在接口返回数据的时候直接一句话搞定。不在需要去model中setData:NSDictionary(以前我就是这样,现在感觉自己像个白痴!!!)了,挺方便的。
2.消息传递
NSArray *ary = @[@"阿卡多好看", @"asasjdkhaskjdh", @"爱上的开奖号阿圣诞快乐啊"];
NSArray *aryLength = [ary valueForKey:@"length"];
只需要一句话,就能获取到上面数组中所有内容的长度。(注意数据类型,如果数组中是对象,他就没有length)。
3.聚合操作 @avg(取平均值) @count(个数) @max(最大值) @min(最小值) @sum(求和)
NSMutableArray *ary = [[NSMutableArray alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(156*i+123123435), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary addObject:p];
}
///每个人的年龄
NSLog(@"%@", [ary valueForKey:@"age"]);
///去所有人的平均值
// NSNumber *num = [ary valueForKeyPath:@"@avg.age"];
NSLog(@"%@", [ary valueForKeyPath:@"@avg.age"]);
3.数组操作 distinctUnionOfObjects (去重) unionOfObjects(不去重)
/**
数组操作符 distinctUnionOfObjects unionOfObjects
*/
- (void)demo4{
NSMutableArray *ary = [[NSMutableArray alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(170 + 0.02*arc4random_uniform(6)), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary addObject:p];
}
NSLog(@"%@", [ary valueForKey:@"accontId"]);
//去重
NSLog(@"%@", [ary valueForKeyPath:@"@distinctUnionOfObjects.accontId"]);
}
以后的开发中,去重就很简单了!
4.嵌套(array)操作 distinctUnionOfArrays unionOfArrays
- (void)demo5{
NSMutableArray *ary = [[NSMutableArray alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(170 + 0.02*arc4random_uniform(6)), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary addObject:p];
}
NSMutableArray *ary1 = [[NSMutableArray alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(170 + 0.02*arc4random_uniform(6)), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary1 addObject:p];
}
//嵌套数组
NSArray *list = @[ary,ary1];
//去重
NSLog(@"%@", [list valueForKeyPath:@"@distinctUnionOfArrays.accontId"]);
//不去重
NSLog(@"%@", [list valueForKeyPath:@"@unionOfArrays.accontId"]);
}
5.另外还有一个集合!!!!
NSMutableSet *ary = [[NSMutableSet alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(170 + 0.02*arc4random_uniform(6)), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary addObject:p];
}
// NSLog(@"%@", [ary valueForKey:@"accontId"]);
NSMutableSet *ary1 = [[NSMutableSet alloc] init];
for (int i = 0; i < 6; i++) {
ZPPerson *p = [ZPPerson new];
NSDictionary *dic = @{@"name": @"Tom", @"age":@(18+i), @"nick":@"壮壮", @"accontId":@(170 + 0.02*arc4random_uniform(6)), @"sex":@"男"};
[p setValuesForKeysWithDictionary:dic];
[ary1 addObject:p];
}
// NSLog(@"%@", [ary1 valueForKey:@"accontId"]);
NSSet *set = [NSSet setWithObjects:ary, ary1, nil];
NSLog(@"%@", [set valueForKey:@"accontId"]);
NSLog(@"%@", [set valueForKeyPath:@"@distinctUnionOfSets.accontId"]);