KVO原理解析和自定义KVO


(1)KVO是基于runtime机制实现的,
(2)类A监听类B的一个属性的变化,当B被观察时,系统会在运行期动态创建一个B的子类NSKVONotifying_B,
(3)每个类都有一个isa指针指向当前类,B的isa指针会指向派生类NSKVONotifying_B,然后重写被观察的属性的setter方法,
(4)键值观察依赖于NSobject的两个方法willChangeValueForKey和didChangeValueForKey,在属性被改变之前调用willChangeValueForKey记录旧值,发生改变之后调用didChangeValueForKey用来储存新值,然后调用observeValueForKey:ofObject:change:context

下图
这里写图片描述


自定义KVO

- (void)Mae_addObserve:(NSObject *)observe forKeyPabth:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context{
        动态添加一个类,模拟子类NSKVONotifying_B的产生
        NSString *oldClassName = NSStringFromClass([self class]);
        NSString *newClassName = [@"Mae" stringByAppentdingString:oldClassName];
        const char *newName = [newClassName UTF8String];
        Class  myClass = objc_allocateClassPair([self class],newName,0);

添加一个setter方法,比如监听的是name属性,添加name的setter方法
class_addMethod(myClass,@selector(setName:),(IMP)(setName),nil);

注册新添加的这个类
objc_registerClassPair(myClass);

将指向被观察者的isa指针,指向新类
object_setClass(self,myclass);

将观察者的属性,保存到新类中去
   objc_setAssociatedObject(self, (__bridge const void *)@"objc", observer, OBJC_ASSOCIATION_RETAIN_NONATOMIC);     
}

//相当于重写父类的方法
void setAge(id self, SEL _cmd, int age) {

    //保存当前类
    Class myclass = [self class];

    //将self的isa指针指向父类
    object_setClass(self, class_getSuperclass([self class]));

    //调用父类
    objc_msgSend(self, @selector(setName:),name);

    //拿出观察者
    objc_getAssociatedObject(self, (__bridge const void *)@"objc");

    //通知观察者
    objc_msgSend(objc,@selector(observeValueForKeyPath:ofObject:change:context:),self,name,nil,nil);

    //改为子类
    object_setClass(self, myclass);
}

这样就可以回调到ViewContoller中的监听方法observeValueForKeyPath:ofObject:change:context:中去,而且相关的值也传递过去了。


如何手动触发KVO
这里写图片描述


KVO的缺陷

你只能通过重写 -observeValueForKeyPath:ofObject:change:context: 方法来获得通知。
想要提供自定义的 selector ,不行;
想要传一个 block ,门都没有。

参考http://tech.glowing.com/cn/implement-kvo/

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值