通过断点可以看到已经被监听的类的isa指针:
(lldb) p self.person->isa
(Class) $0 = NSKVONotifying_WPPerson
问题是NSKVONotifying_WPPerson何时来的,我尝试在添加监听之前还有之后分别打印NSClassFromString(@"NSKVONotifying_WPPerson")发现NSKVONotifying_WPPerson是在添加观察者之后被创建的.
通过打印NSKVONotifying_WPPerson这个类的方法列表:
- (void)printMethods:(Class)class{
unsigned int count = 0;
Method *methods = class_copyMethodList(class, &count);
for (int i = 0; i < count; i++) {
Method method = methods[i];
SEL sel = method_getName(method);
IMP imp = method_getImplementation(method);
NSString *methodName = NSStringFromSelector(sel);
NSLog(@"%@",methodName);
}
}
2019-01-14 16:11:27.591359+0800 KVO_learn[35003:466572] setArray:
2019-01-14 16:11:36.150872+0800 KVO_learn[35003:466572] class
2019-01-14 16:11:40.639886+0800 KVO_learn[35003:466572] dealloc
2019-01-14 16:22:35.932556+0800 KVO_learn[35003:466572] _isKVOA
断点发现IMP都是指向Foundition框架的
一般的内部执行过程是:
NSKeyValueWillChange
[WPPerson setSteps:]
NSKeyValueDIdChange
NSKeyValueNotifyObserver
observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change
主要注意的是移除观察者时:
1:移除之后isa指针指向了WPPerson
2:但是NSKVONotifying_WPPerson这个类已经被注册过了,不会被销毁,只是ISA指针改变了