- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context {
DSKeyValueProperty * property = DSKeyValuePropertyForIsaAndKeyPath(object_getClass(self),keyPath);
Class isaForAutonotifying = [property isaForAutonotifying];
if(isaForAutonotifying) {
Class cls = object_getClass(self);
// 把当前类的isa指向动态创建的子类
if(cls != isaForAutonotifying) {
object_setClass(self,isaForAutonotifying);
}
}
}
- (Class)isaForAutonotifying {
// 动态创建一个子类
Class subClass = objc_allocateClassPair(originalClass, newClassName, sizeof(DSKeyValueNotifyingInfo));
objc_registerClassPair(subClass);
// 为子类添加四个方法
class_addMethod(subClass, @selector(_isKVOA), NSKVOIsAutonotifying, encoding);
class_addMethod(subClass, @selector(dealloc), NSKVODeallocate, encoding);
class_addMethod(subClass, @selector(class), NSKVOClass, encoding);
class_addMethod(subClass, @selector(setXXX), _NSSetObjectValueAndNotify, encoding);
return subClass;
}
Class NSKVOClass(id object, SEL selector) {
// 返回调用父类的class方法
return [originalClass class];
}
void _NSSetObjectValueAndNotify(id object,SEL selector, id value) {
NSKeyValueWillChange();
// keypath嵌套的情况下调用下面两句
[changingRelationshipObject removeObserver:observance forKeyPath:_keyPathFromRelatedObject];
[newRelationshipObject addObserver:observance forKeyPath:_keyPathFromRelatedObject options:option context:context];
// 调用父类的setter
IMP imp = class_getMethodImplementation(info->originalClass, selector);
setValueWithImplementation(imp);
NSKeyValueDidChange();
}
void NSKeyValueDidChange(id object, id keyOrKeys, BOOL isASet,DSKVODidChangeDetailSetupFunc didChangeDetailSetupFunc, DSKVODidChangeNotificationPopFunc didChangeNotificationPopFunc, void *popInfo) {
遍历所有的observer {
[observer observeValueForKeyPath:keyPath ofObject:object change:changeDictionary context:context];
}
}
KVO底层伪代码
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。
推荐阅读更多精彩内容
- 需求背景: 我们的App中有好多弹窗和浮层,活动、更新、新手引导、初次加载的三帧引导、和不同页面不定时的弹个确...
- 当观察某对象 A 时,KVO 机制动态创建一个对象A当前类的子类,并为这个新的子类重写了被观察属性 keyPath...