. 1kvo ios 用什么方式实现对一个对象的KVO ? (KVO 的本质是什么?)
监听的原理是从写set方法 更换 所以 能否监听 是需要判断 有没有 set方法
为什么新生成的类没有get方法 , 因为 父类有了,不需要重写和这个无意义
利用runtime 动态生成子类 并且让 isa 指向全新的子类 , 当修改实例对象的属性时 会调用 foundation 的_NSSet*ValueForKeyNotify (will super did) did 方法 会出发 监听方法 observeValuefoKeyath:
2. 如何手动触发KVO
[self.person willCHangeForkey@age"]; [self person didchangevalueforKey:@"age"];
didchange 内部会判断willchange 是否被调用了, 所以需要先调用 willchangeg方法
- 直接修改成员变量会出发KVO 吗 ?
{ int _age; }
self.person.age = 2: 会调动 self.person ->age = 2, 不会调
不会, 因为没有调用set方法
kvo key-value observing 键值监听
// 添加监听 NSKeyvalueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
[self.person addObserviing:self forKeyPath:@"age" options:options context:@"sd"]; // 移除监听
- (void)dealloc { [self.person removeObser:self forKeyPath:@"age"]; }
// 值改变的时候回调用
-
(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(id) change context:(void *)context { nslog( @"%@",newValue); }
-
(void)changeValue {
self.person1.age = 21; self.perdon2.age = 22;
}
- (void)setAge:(nsintering) age{ _age = age; }
两个set 方法都执行了但是只有person1 会 调用监听方法
查看流程 首先查看 isa指针
lldb p self.person1.isa (Class) $0 = NSKVONotifying_Person 使用KVO 监听 isa 指针变了 Fix-it applied, fixed expression was : self.person1.isa
lldb p self,person2.isa (Class) $1 = Person // 未使用KVO 监听 isa 指针不变
NSKVONotifying_Person Class 是 runtime 运行中动态创建的类, 是person 的子类 , 他的superClass 指向了 person
全新的这个类中 的类对象 重写了 四个方法 , setAge: class deallock _isKVOA
派生类的setAge: 方法会拦截 方法的查找 ,
person 调用 setAge: 会调用Foundation 框架中的_NSSetIntValueAndNotify
类似这样
@implementation NSKVONotifying_Person
-
(void)setAge:(int)age {
_NSSetIntValueAndNotify();
}
void _NSSetIntValueAndNotify() { //伪代码 [self willChangeValueForKey:@"age"]; [super setAge:age]; [self didChangeValueForKey:@"age"]; }
- (void)didChangeValueForKey:(Nssting *)key { // 通知监听器 属性发生改变 self observeValueForkeyPath:()path ofObject:()object change:()cange content:()content
}
-
(Class)class {
return seuper Classs }
-
(void)delloc {
}
- (Bool)_isKVOA { }
@end
[ person1 class]; [person2 class];
NSlog(objc_getClass(person1))
NSKVONotifying_Person
NSlog(person class)
Person
使用runtime 获取类和 preson class 不一样, runtime 获取的是真的类
class 方法 是获取从写的 Class 方法 获取 苹果不想暴露真实类型 屏蔽内部实现 隐藏了类的实现
- (void)printMethodNamesOfClass:(Class)cls {
}
关于动态生成子类
objc_allocateClassPair and before objc_regsterClassPair