OC语言之KVO与KVC
2019-06-14 本文已影响0人
Jimmy_L_Wang
KVO
什么是KVO?
- KVO 是 Key-value observing(键值观察)的缩写。
- KVO是Objective-C对观察者设计模式的又一实现。
- Apple使用了isa混写(isa-swizzling)来实现KVO。
KVO的实现机制是怎样的?

系统在运行时为我们动态创建了一个子类NSKVONotifying_A
,改写isa的指向为这个子类,同时重写setter方法,来实现KVO的机制的
系统会在创建的NSKVONotifying_A
的重写setter
中调用下面两个方法:
//NSKVONotifying_A的setter实现
- (void)setValue:(id)obj
{
[self willChangeValueForKey:@"keyPath"];
//调用父类实现,也即原类的实现
[super setValue:obj];
//此方法会触发observeValueForKeyPath:回调
[self didChangeValueForKey:@"keyPath"];
}
通过KVC设置value能否生效?
能,为什么可以生效。KVC的setValue:forKey:
可以调用到被监听对象的setter
方法。
通过成员变量直接赋值value能否生效?
不能。因为不能调用到被监听对象的setter
方法。
如何实现手动的KVO监听
- (void)increase
{
//直接为成员变量赋值
[self willChangeValueForKey:@"value"];
_value += 1;
[self didChangeValueForKey:@"value"];//会触发observeValueForKeyPath:回调
}
Ps:监听者回调
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{
if ([object isKindOfClass:[MObject class]] &&
[keyPath isEqualToString:@"value"]) {
// 获取value的新值
NSNumber *valueNum = [change valueForKey:NSKeyValueChangeNewKey];
NSLog(@"value is %@", valueNum);
}
}
KVC
- KVC是Key-value coding(键值编码)的缩写。
- (void)setValue:(nullable id)value forKey:(NSString *)key;
- (nullable id)valueForKey:(NSString *)key;
KVC是否有违背面向对象编程思想?
是的,上面的key
是没有任何限制的,在我们知道一个类或实例它内部的某一个私有成员变量名称的情况下,我们在外界是可以通过已知的key
来对他的私有成员变量进行设置或访问的操作,从这个层面上来讲是破坏了面向对象编程思想的。
valueForKey:
的系统实现流程?

Accessor Method是否存在的判断规则
<getKey>
<key>
<isKey>
Instance var
-
_key
-
_isKey
-
key
-
isKey
setValue: forKey:调用流程
