- (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...