1. KVO的完成原理
- 经过
runtime
派生子类的办法复写相关需求KVO监听的特点, 在该特点setter之前和之后调用NSObject的监听办法, 这样KVO就完成了特点变换前后的回调. - KVO派生的子类详细格局应该是:
NSKVONotifying_+类名
的类, 如NSKVONotifying_Person
- 未运用KVO监听的目标的isa指针结构图
- 运用了KVO监听的目标的isa指针结构图
-
_NSSetValueAndNotify
的内部完成
- 子类的内部办法
-
class
办法屏蔽了内部完成, 躲藏了NSKVONotifying_MJPerson
类的存在, runtime能够拿到实在的类型
2. 怎么手动触发一个KVO
- 键值调查通知依赖于NSObject的两个办法
-
willChangeValueForKey:
-
didChangeValueForKey:
- 在一个被调查特点产生改动之前,
willChangeValueForKey:
一定会被调用, 这就会记载旧的值. - 当改动产生后,
didChangeValueForKey:
会被调用, 继而observeValueForKey:ofObject:change:context
也会被调用. - 假如能够手动完成这些调用, 就能够完成”手动触发KVO”了.
3. 怎么给体系KVO设置筛选条件?
- 如:取消
Person
类age
特点的默认KVO, 设置age大于18时, 手动触发KVO
+ (BOOL)automaticallyNotifiesObserversForKey:(NSString *)key {
if ([key isEqualToString:@"age"]) {
return NO;
}
return [super automaticallyNotifiesObserversForKey:key];
}
- (void)setAge:(NSInteger)age {
if (age >= 18) {
[self willChangeValueForKey:@"age"];
_age = age;
[self didChangeValueForKey:@"age"];
} else {
_age = age;
}
}
4. 经过KVC修正特点会触发KVO吗?
- 会触发KVO, 即使没有声明特点, 只需成员变量, 只需
accessInstanceVariablesDirectly
回来的是YES, 允许拜访其成员变量, - 那么不论有没有调用setter办法, 经过KVC修正成员变量的值, 都会触发KVO.
- 这也说明经过KVC内部完成了
willChangeValueForKey:
办法和didChangeValueForKey:
办法.
5. 直接修正成员变量会触发KVO吗?
- 不会触发KVO, 直接修正成员变量内部并没有做处理仅仅单纯的赋值, 所以不会触发KVO.
6. KVC的底层完成是什么?
- 赋值办法
setValue:forKey:
的原理
- 首先会依照次序一次查找
setKey:
办法和_setKey:
办法, 只需找到这两个办法当中的任何一个就直接传递参数, 调用办法; - 假如没有找到
setKey:
和_setKey:
办法, 那么这个时分会检查accessInstanceVariablesDirectly
办法的回来值, 假如回来NO(也就是不允许直接拜访成员变量), 那么会调用setValue:forUndefineKey:
办法, 并抛出反常NSUnknownKeyException
; - 假如
accessInstanceVariablesDirectly
办法回来的是YES, 也就是说能够拜访其成员变量, 那么就会依照次序一次查找_key、_isKey、key、isKey
这四个成员变量, 假如查找到了, 就直接赋值; 假如依然没有查到, 那么会调用setValue:forUndefineKey:
办法, 并抛出反常NSUnknownKeyException
.
- 取值办法
valueForKey:
的原理
- 首先会依照次序一次查找
getKey:、key、isKey、_key:
这四个办法, 只需找到这四个办法当中的任何一个就直接调用该办法; - 假如没有找到, 那么这个时分会检查
accessInstanceVariablesDirectly
办法的回来值, 假如回来的是NO(不允许直接拜访成员变量), 那么会调用valueforUndefineKey:
办法, 并抛出反常NSUnknownKeyException
; - 假如
accessInstanceVariablesDirectly
办法回来的是YES, 也就是说能够拜访其成员变量, 那么就会依照次序一次查找_key、_isKey、key、isKey
这四个成员变量, 假如找到了, 就直接取值; 假如依然没有找到成员变量, 那么会调用valueforUndefineKey
办法, 并抛出反常NSUnknownKeyException
.
7. KVC的运用
- 动态地取值和设置值
- 拜访和修正私有变量
-
- 修正一些控件的内部特点
-
- 如之前的
UITextField
的placeHolderText
.
- 如之前的
- 模型和字典的转换
8. KVO的优缺陷
8.1 KVO的优点:
- 能够供给一种简略的办法完成两个目标间的同步.如
Model
和View
之间同步. - 能够对内部目标(非咱们创立的目标)的状态改动做出呼应, 而不需求改动内部目标的完成.
- 能够供给所调查特点的最新值和之前的旧值.
- 经过
addObserver: forKeyPath
来调查特点, 因此能够调查嵌套目标.
8.2 KVO的缺陷
- 咱们调查的特点有必要运用
String
来定义. 编译时, 编译器不会发出警告及检查. - 对特点的重构会导致咱们的调查代码不再可用.
- 一切的调查代码经过一个办法来做, 会生成杂乱的if语句.
- 被调查者开释时, 不需求移除调查者, 会形成闪退.