KVO的底层是怎么实现的?

作者: 海绵宝宝不要哭 | 来源:发表于2016-04-21 11:58 被阅读216次

    KVO的底层是怎么实现的?

    1:KVO是基于Runtime机制实现的
    2:当某个类的对象第一次被观察时,系统就会在运行期动态的创建该类的一个派生类,在这个派生类中重写基类以及被观察属性的setter方法,派生类在被重写的setter方法实现真正的通知机制(Person->NSKVONotifying_Person)

    后面我们对KVO的底层进行一个分析

    业务需求

    人的年龄改变了,那么狗得知道人的年龄改变了

    1:我们先新建一个项目

    屏幕快照 2016-04-21 上午10.55.38.png

    2:新建两个类
    a:一个Person类

    Person 有一个age年龄属性
    

    b: 一个Dog类

    屏幕快照 2016-04-21 上午10.58.44.png

    3:我们在ViewController去实现点击屏幕修改person的年龄属性

    #import "ViewController.h"
    #import "Person.h"
    #import "Dog.h"
    
    
    @interface ViewController ()
    @property (nonatomic, strong) Person *person;
    @property (nonatomic, strong) Dog *dog;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.person = [[Person alloc]init];
        self.dog = [[Dog alloc]init];
    
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        self.person.age = 10;
    }
    @end
    
    

    4:接下来再去给person增加一个方法

    #import "ViewController.h"
    #import "Person.h"
    #import "Dog.h"
    
    
    @interface ViewController ()
    @property (nonatomic, strong) Person *person;
    @property (nonatomic, strong) Dog *dog;
    @end
    
    @implementation ViewController
    
    - (void)viewDidLoad {
        [super viewDidLoad];
        
        self.person = [[Person alloc]init];
        self.dog = [[Dog alloc]init];
    
        //这个方法的意思是什么,就是让self.dog知道self.person,的age改变了,也就是self.dog成为self.person的监听
        [self.person addObserver:self.dog forKeyPath:@"age" options:0 context:nil];
    }
    
    -(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
        
        self.person.age = 10;
    }
    @end
    
    

    5:接下来我们去Dog类里面实现一个方法(注意注释)

    #import "Dog.h"
    
    @implementation Dog
    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
        
        //这个方法什么意思?来到这里其实就是狗知道了person的年龄改变了
        NSLog(@"狗知道了%@的%@改变了",object,keyPath);
    }
    @end
    
    

    6:我们把项目运行起来,看是否实现我们的需求

    屏幕快照 2016-04-21 上午11.21.43.png

    可以看到,控制台输出了,狗知道了person的age改变了

    7:此时我们就简单的实现了我们的需求,是用的是KVO去实现
    那KVO的底层到底是怎么实现的呢?为什么会去调用Dog的

    -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
        
        //这个方法什么意思?来到这里其实就是狗知道了person的年龄改变了
        NSLog(@"狗知道了%@的%@改变了",object,keyPath);
    }
    
    

    8:其实是这样,我们KVO监听的属性被改变的时候,系统会给我们生存一个派生类,并且这个类是继承Person类的,并且在年龄改变的时候,会重写属性的setter方法

    屏幕快照 2016-04-21 上午11.26.56.png

    可能大家还不觉得是真的重写了这个类的setter方法,我给大家看一下他Person的isa指针到底是啥。

    Snip20160421_2.png

    相关文章

      网友评论

        本文标题:KVO的底层是怎么实现的?

        本文链接:https://www.haomeiwen.com/subject/ceetrttx.html