KVC详解

作者: lmfei | 来源:发表于2019-11-20 10:20 被阅读0次

KVC定义

KVC(Key-value coding)键值编码。通过<Key>来直接访问对象的属性,或者为属性赋值,而不是通过明确的set/get方法,这样就可以再运行时动态的访问和修改对象的属性,而不是在编译时确定,它是iOS开发的黑魔法之一,它是很多黑魔法的基础。

注:KVC与点语法有什么区别?
在实现了set\get方法的类中,两者没有太大差异。但是在没有实现set\get方法的类中,点语法无法使用,这时KVC的优势就体现出来了。

KVC的使用

KVC的定义都是对NSObject的扩展来实现的,所以对于所有继承NSObject的类都能使用KVC。
常用的API

//通过key取值
- (nullable id)valueForKey:(NSString *)key;
//通过key设值
- (void)setValue:(nullable id)value forKey:(NSString *)key;
//通过keyPath取值
- (nullable id)valueForKeyPath:(NSString *)keyPath;
//通过keyPath设值
- (void)setValue:(nullable id)value forKeyPath:(NSString *)keyPath;
//验证属性值是否满足条件
- (BOOL)validateValue:(inout id _Nullable * _Nonnull)ioValue forKey:(NSString *)inKey error:(out NSError **)outError;
//取值时如果key不存在,则会调用这个方法,抛出异常
- (nullable id)valueForUndefinedKey:(NSString *)key;
//设值时如果key不存在,则会调用这个方法,抛出异常
- (void)setValue:(nullable id)value forUndefinedKey:(NSString *)key;
//如果设值时,该属性值不支持nil,则会调用这个方法
- (void)setNilValueForKey:(NSString *)key;
setValue:forKey流程图
setValue_forKey

流程图概述如下:

  • 优先查找set<key>:方法,如果找到执行方法,如果没有找到,再查找_set<key>,如果找到执行方法,如果没有找到,执行下一步
  • 检查accessInstanceVariablesDirectly的返回值,如果返回NO,则执行setValue:forUndefinedKey:抛出异常,如果返回YES,默认返回YES,执行下一步
  • 按照以下顺序,依次查找成员变量:_<key>、_is<key>、<key>、is<key>,找到则赋值,如果任未找到则调用setValue:forUndefinedKey:然后抛出异常
valueForKey:流程图
valueForKey流程图

流程图概述如下:

  • 首先按get<key>、<key>、is<key>的顺序查找getter方法,找到直接调用,没有找到执行下一步
  • 查找countOf<Key>,objectIn<Key>AtIndex或<Key>AtIndexes方法,如果countOf<Key>和另外两个方法中的一个被找到,那么就会返回一个NSArray集合,否则执行下一步
  • 查找countOf<Key>,enumeratorOf<Key>,memberOf<Key>方法,如果三个方法都找到,那么就返回一个NSSet集合
  • 检查accessInstanceVariablesDirectly的返回值,如果返回NO,则执行valueforUndefinedKey:抛出异常,如果返回YES,默认返回YES,执行下一步
  • 按照以下顺序,依次查找成员变量:_<key>、_is<key>、<key>、is<key>,找到则取值,如果任未找到则调用valueforUndefinedKey:然后抛出异常
KVC处理异常
nil异常

在设值时,给值类型传了nil,则会调用setNilValueForKey:,默认抛出异常,
重写该方法则不抛出异常

undefinedKey异常

在设值时对不存在的key进行了操作,会报错setValue: forUndefinedKey:,重写该方法避免崩溃

KVC使用场景
  1. 动态地存取值
  2. 访问和修改私有变量、修改控件的内部属性
[self.textField setValue:[UIColor orangeColor] forKeyPath:@"_placeholderLabel.textColor"];
  1. model和字典之间的转换
- (void)kvc_dict {
    //modal->dict
    LPersona *per = [LPersona new];
    [per setValue:@10 forKey:@"age"];
    [per setValue:@170 forKey:@"height"];
    [per setValue:@70 forKey:@"weight"];
    [per setValue:@"M" forKey:@"hex"];

    NSArray *arr = @[@"age", @"height", @"weight", @"hex"];
    NSDictionary *dict = [per dictionaryWithValuesForKeys:arr];
    NSLog(@"modal->dict:%@",dict);
    
    //dict->moal
    LPersona *per2 = [LPersona new];
    NSDictionary *tempDic = @{@"age":@17, @"height":@175, @"weight":@75, @"hex":@"W"};
    [per2 setValuesForKeysWithDictionary:tempDic];
    NSLog(@"age:%@, height:%@, weight:%@, hex:%@",[per2 valueForKey:@"age"],[per2 valueForKey:@"height"],[per2 valueForKey:@"weight"],[per2 valueForKey:@"hex"]);
}
  1. 操作集合
- (void)kvc_group {
    LPersona *p1 = [LPersona new];
    [p1 setValue:@10 forKey:@"age"];
    [p1 setValue:@"M" forKey:@"hex"];

    LPersona *p2 = [LPersona new];
    [p2 setValue:@20 forKey:@"age"];
    [p2 setValue:@"W" forKey:@"hex"];

    LPersona *p3 = [LPersona new];
    [p3 setValue:@30 forKey:@"age"];
    [p3 setValue:@"M" forKey:@"hex"];

    LPersona *p4 = [LPersona new];
    [p4 setValue:@40 forKey:@"age"];
    [p4 setValue:@"W" forKey:@"hex"];

    LPersona *p5 = [LPersona new];
    [p5 setValue:@10 forKey:@"age"];
    [p5 setValue:@"M" forKey:@"hex"];

    //简单集合运算
    NSArray *arr = @[p1,p3,p2,p5,p4];
    NSNumber *sum = [arr valueForKeyPath:@"@sum.age"];
    NSLog(@"sum:%@",sum);
    
    NSNumber *avg = [arr valueForKeyPath:@"@avg.age"];
    NSLog(@"avg:%@",avg);
    
    NSNumber *count = [arr valueForKeyPath:@"@count.age"];
    NSLog(@"count:%@",count);

    NSNumber *min = [arr valueForKeyPath:@"@min.age"];
    NSLog(@"min:%@",min);

    NSNumber *max = [arr valueForKeyPath:@"@max.age"];
    NSLog(@"max:%@",max);
    
    //去重
    NSArray *distinct = [arr valueForKeyPath:@"@distinctUnionOfObjects.age"];
    NSLog(@"distinctUnionOfObjects-----------");
    for (NSNumber *age in distinct) {
        NSLog(@"%f", age.floatValue);
    }
    
    //全集
    NSArray *arrUnion = [arr valueForKeyPath:@"@unionOfObjects.age"];
    NSLog(@"unionOfObjects-----------");
    for (NSNumber *age in arrUnion) {
        NSLog(@"%f", age.floatValue);
    }
}

打印结果:

2019-11-19 11:05:29.556863+0800 KVC探究一[2925:7723768] sum:110
2019-11-19 11:05:29.557050+0800 KVC探究一[2925:7723768] avg:22
2019-11-19 11:05:29.557138+0800 KVC探究一[2925:7723768] count:5
2019-11-19 11:05:29.557219+0800 KVC探究一[2925:7723768] min:10
2019-11-19 11:05:29.557292+0800 KVC探究一[2925:7723768] max:40
2019-11-19 11:05:29.557715+0800 KVC探究一[2925:7723768] distinctUnionOfObjects-----------
2019-11-19 11:05:29.557903+0800 KVC探究一[2925:7723768] 10.000000
2019-11-19 11:05:29.557957+0800 KVC探究一[2925:7723768] 20.000000
2019-11-19 11:05:29.558009+0800 KVC探究一[2925:7723768] 30.000000
2019-11-19 11:05:29.558126+0800 KVC探究一[2925:7723768] 40.000000
2019-11-19 11:05:29.558337+0800 KVC探究一[2925:7723768] unionOfObjects-----------
2019-11-19 11:05:29.558518+0800 KVC探究一[2925:7723768] 10.000000
2019-11-19 11:05:29.559370+0800 KVC探究一[2925:7723768] 30.000000
2019-11-19 11:05:29.559471+0800 KVC探究一[2925:7723768] 20.000000
2019-11-19 11:05:29.559601+0800 KVC探究一[2925:7723768] 10.000000
2019-11-19 11:05:29.559654+0800 KVC探究一[2925:7723768] 40.000000

  1. KVO
    强大的KVO,竟然是基于KVC的

生活如此美好,今天就点到为止。。。

相关文章

  • iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

    iOS开发技巧系列---详解KVC(我告诉你KVC的一切) iOS开发技巧系列---详解KVC(我告诉你KVC的一切)

  • iOS日记15-KVC

    1.iOS开发技巧系列---详解KVC 2.漫谈 KVC 与 KVO 3.KVC/KVO原理详解及编程指南 关键点...

  • iOS 关于KVC的一些总结

    本文参考: KVC官方文档 KVC原理剖析 iOS KVC详解 KVC 简介 KVC全称是Key Value Co...

  • iOS 关于KVC的一些总结(转)

    原文:iOS 关于KVC的一些总结 本文参考: KVC官方文档 KVC原理剖析 iOS KVC详解 KVC 简介 ...

  • iOS Objective-C KVC 详解

    iOS Objective-C KVC 详解 1. KVC简介 KVC 全称Key Value Coding,是苹...

  • iOS-- KVC

    推荐一篇超好的KVC详解博客:《详解KVC,我来告诉你KVC的一切》,看完之后顿时觉得自己没啥写的, 分享一下。

  • OC--KVC

    参考:iOS开发技巧系列---详解KVC(我告诉你KVC的一切)KVC原理剖析 NSObject(NSKeyVal...

  • 详解KVO,KVC

    转自小菜鸟dxb => 详解KVO,KVC 1、KVC,即是指 NSKeyValueCoding,一个非正式的Pr...

  • KVC 和 KVO详解

    KVC 详解 KVC : 键值编码(Key-Value Coding),它是一种通过key值访问类属性的机制,而不...

  • KVC详解

    KVC(Key-valueCoding) KVC键值编码,是对NSObjcet的扩展,分类名为:NSKeyValu...

网友评论

      本文标题:KVC详解

      本文链接:https://www.haomeiwen.com/subject/yvdvictx.html