ios-手动实现KVO简单版

知道KVO的实现原理的应该都知道,其实在我们去设置监听对象的属性的时候,对象的类会在运行时被改变,改成系统生成的一个类,会在这个子类中重写被观察属性的方法,当然也会去调用原本属于那个类中的set方法。之后再把类给改回去,关于KVO的实现可以详细请看http://blog.csdn.net/zcmuczx/article/details/78620680

所以我们当然也可以利用runtime来进行模拟这个过程,下面就直接上代码。

我们如果想自己实现的话其实就是去创建我们需要监听的类的那个子类,然后去修改要监听对象的isa指针指向我们创建的子类之后去重写setName的方法,然后在setName方法中修改isa指针指向父类,然后去调用父类的setName方法,之后通知观察者,然后把isa指针再改回指向子类。

大致的步骤的话其实就是在NSObject的分类中模仿addObserve添加一个方法,然后让外界去调用

#import "NSObject+ZXKVO.h"
#import <objc/message.h>
@implementation NSObject (ZXKVO)
-(void)ZX_addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options
 context:(void *)context
{
    //1、首先先去动态的生成一个类
    //先去获取旧的类名
    NSString * oldClassName = NSStringFromClass([self class]);
    //先去构建新的类名
    NSString * name = [@"NSZX_" stringByAppendingString:oldClassName];
    //获得新的类名
    const char * newClassName = [name UTF8String];
    //创建新的一个类
    Class newClass = objc_allocateClassPair([self class], newClassName, 0);
    //我们需要去添加一个setName的方法,其实也就相当于是重写这个setName方法,因为我们需要这里面做事情也就是去做我们外面监听属性变化所做的事情
    class_addMethod(newClass, @selector(setName:), (IMP)setName, "");
    
    //注册这个类
    objc_registerClassPair(newClass);
    
    //修改被观察者的isa的指针,指向我们定义的类
    object_setClass(self, newClass);
    
    //要先去动态的去绑定observer,因为我们需要在下面中去取到observer
    objc_setAssociatedObject(self, @"key", observer, OBJC_ASSOCIATION_RETAIN);
    
}
void setName(id self,SEL _cmd,NSString * newName)
{
    //获取当前的类型
    id class = [self class];
    
    //去修改当前的对象的isa的指向,让其指向父类
    object_setClass(self, class_getSuperclass([self class]));
    
    /*调用父类的setName的方法,因为如果这里不调用的话,那么我们在ZX_addObserver中已经修改了类的指向,而且下面的方法已经被实现,   
    所以不会去调用父类的setName方法*/
    objc_msgSend(self, @selector(setName:),newName);
    
    //然后拿出观察者
    id observer = objc_getAssociatedObject(self, @"key");
    
    //通知外界
    objc_msgSend(observer, @selector(observeValueForKeyPath:ofObject:change:context:),self,@"name",@{@"newString":newName},nil);
    //改回成子类的类型
    object_setClass(self, class);
    
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值