Objective - C KVC

作者: 爱玩游戏的iOS菜鸟 | 来源:发表于2020-04-30 23:33 被阅读0次

(一)KVC (Key-Value Coding)

KVC,即键值编码,通过key来访问属性

(1)常见的API
  • - (void)setValue:(id)value forKeyPath:(NSString *)keyPath;
  • - (void)setValue:(id)value forKey:(NSString *)key;
  • - (id)valueForKeyPath:(NSString *)keyPath;
  • - (id)valueForKey:(NSString *)key;
(2)访问属性常规用法
  1. 设置
  • setValue: forKey:设置对象的属性值(单层)
  • setValue: forKeyPath:可以设置属性的属性(可以多层)
  self.person = [[ZQPerson alloc]init];
  //setValue: forKey:方法
  [self.person setValue:@10 forKey:@"age"];
  self.person.dog = [[ZQDog alloc] init];
 //setValue: forKeyPath:方法
  [self.person setValue:@20 forKeyPath:@"dog.height"];
  1. 访问(同理)
  • valueForKeyPath:
  • valueForKey:
  //输出10 10
  NSLog(@"%@ %@",[self.person valueForKey:@"age"],[self.person valueForKeyPath:@"dog.height"])
疑问:通过KVC设置成员变量的值,会触发KVO吗?
- (void)viewDidLoad {
    [super viewDidLoad];

    self.person = [[ZQPerson alloc]init];

    [self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
    [self.person setValue:@20 forKey:@"age"];

}

-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"%@  %@  %@",keyPath,object,change);
}

-(void)dealloc{
    [self.person removeObserver:self forKeyPath:@"age"];
}

输出结果:会触发!

age  <ZQPerson: 0x60000026a5e0>  {
    kind = 1;
    new = 20;
    old = 0;
}

到底是什么原因呢?

(3)设值原理

①设置ZQPerson的_age成员变量为私有,添加两个方法(如下),重新运行

//ZQPerson.h
@interface ZQPerson : NSObject{
    int _age;
}

-(void)setAge:(int)age;

-(void)_setAge:(int)age;

@end

//ZQPerson.m
@implementation ZQPerson

-(void)setAge:(int)age{
    _age = age;
    NSLog(@"setAge:%d",age);
}

-(void)_setAge:(int)age{
    _age = age;
    NSLog(@"其次找这里");
}

@end

输出结果:

setAge:20

age  <ZQPerson: 0x600003304ac0>  {
    kind = 1;
    new = 20;
    old = 0;
}

②接着注释掉setAge,再次执行:

_setAge:20

age  <ZQPerson: 0x600002b442d0>  {
    kind = 1;
    new = 20;
    old = 0;
}

我们可以得出结论一:
setValue: forKey:方法首先会查找setKey,_setKey的优先顺序先查找方法

④我们删除所有的set相关方法,重新运行:

age  <ZQPerson: 0x6000015d5cc0>  {
    kind = 1;
    new = 20;
    old = 0;
}

KVO依然会触发!!!

⑤继续,我们重写+(BOOL)accessInstanceVariablesDirectly方法,返回NO,发现报错了valueForUndefinedKey

reason: '[<ZQPerson 0x6000029ac7f0> valueForUndefinedKey:]: this class is not key value coding-compliant for the key age.'

我们可以得出结论二:
如果没有找到方法,会判断该方法是否允许查找成员变量,不允许的情况下直接报错

⑥接下来,我们将+(BOOL)accessInstanceVariablesDirectly返回YES,添加_age,_isAge,age,isAge四个成员变量:

@interface ZQPerson : NSObject{
    int _age;
    int _isAge;
    int age;
    int isAge;
}

@end

运行结果:

接下来不管是怎么注释,或者更换顺序,赋值也是按照这个优先顺序给成员变量赋值
我们可以得出结论三:
若方法是否允许查找成员变量,则会按照_age,_isAge,age,isAge的优先顺序给成员变量赋值,如果找不到,还是会报错valueForUndefinedKey

下面对上面的验证流程做一个总结:


accessInstanceVariablesDirectly方法的默认返回值是YES

只要通过setValue: forKey:的方法,只要赋值成功了,就会触发KVO(自己可以去代码验证)
可能在赋值过程内部,调用了willChangeValueForKey:didChangeValueForKey:,可以通过重写这两个方法,发现确实会调用这两个方法(验证流程省略)

(4)取值原理
验证流程省略

相关文章

  • KVO KVO 温习

    KVC 与 KVO 是 Objective-C 的关键概念. KVC: KVC,即是指 NSKeyValueCod...

  • iOS Objective-C KVC 详解

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

  • KVC 和 KVO

    iOS-KVC和KVO精炼讲解(干货)KVC 和 KVOiOS开发系列--Objective-C之KVC、KVO细...

  • KVC

    iOS 如何使用KVC iOS开发UI篇—Kvc简单介绍 iOS开发系列--Objective-C之KVC、KVO

  • Objective - C KVC

    (一)KVC (Key-Value Coding) KVC,即键值编码,通过key来访问属性 (1)常见的API ...

  • [转]KVO & KVC

    本文转自:Objective-C中的KVC和KVO. KVC KVO2.1. Registering for Ke...

  • KVC、KVO

    IOS开发系列--Objective-C之KVC、KVO - KenshinCui - 博客园

  • KVC/KVO理解

    KVC 与 KVO 是 Objective C 的关键概念,是必须要理解的东西 下面是实例讲解。 一、KVC – ...

  • iOS面试题:KVC的赋值和取值过程是怎样的?KVO原理是什么?

    更多:iOS面试题大全 1、KVC赋值 2、 KVC取值 3、 KVO原理 KVO 是 Objective-C 对...

  • 探索Objective-C的KVC实现

    KVC Objective-C作为一门动态语言,NSObject 里面提供了动态取设值的方法 这就是 KVC (全...

网友评论

    本文标题:Objective - C KVC

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