之前的文章提到过KVO
的实现原理
KVO的实现原理
那么今天来介绍一下KVC
, 什么是KVC
呢?
Key-value-coding
, 也叫键值编码
它有这么几个API
:
setValue: forKey:
setValue: forKeyPath:
valueForKey:
valueForKeyPath:
key
和keyPath
有什么区别呢?
keyPath
顾名思义, 有路径的意思, 举个例子:
- (void)viewDidLoad {
[super viewDidLoad];
Person *p = [Person new];
self.p = p;
self.p.cat = [Cat new];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
[self.p setValue:@"tsaievan" forKey:@"name"];
[self setValue:@10 forKeyPath:@"p.cat.weight"];
NSLog(@"姓名%@", [self valueForKeyPath:@"p.name"]);
NSLog(@"🐱的体重%@", [self valueForKeyPath:@"p.cat.weight"]);
}
keyPath
是可以按照点语法的路径去赋值和取值的
那么使用KVC
会触发KVO
吗?
回答: 会
流程是这样子的, 当调用setValue: forKey:
时, 首先是按照顺序
-
setKey:
(举个例子, 如果key
是name
, 那方法名就是setName:
) -
_setKey:
(同上)
查找方法, 如果有方法, 就直接调用
我们知道,KVO
是重写了set
方法, 那如果找到了这个set
方法, 直接调用的话, 就会触发KVO
如果没有找到方法, 就要看accessInstanceVariablesDirectly
这个方法, 这个方法默认返回时YES
的, 如果重写了这个方法, 返回NO
的话, 程序就会抛出异常.
返回YES
之后, 会按照
_key
_isKey
key
-
isKey
的顺序去查找这个类有没有这些成员变量, 有就直接赋值, 没有就抛出异常.
那么, 直接赋值是会触发KVO
吗? 答案也是肯定的.
在setValue: forKey:
的方法中, 可能会先调用willChangeValueForKey:
, 然后再给变量赋值, 最后调用didChangeValueForKey:
, 触发KVO
再来看看valueForKey:
基本流程和setValue: forKey:
差不多
网友评论