zoukankan      html  css  js  c++  java
  • KVO的底层实现

    1.首先了解什么是KVO 

    KVO 即Key-Value Observing ,他提供一种机制,当指定的对象的属性被修改后,则对象就会接受到通知,简单的说就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知

    相应的观察者了.

    下面举个例子进行说明

    1.创建一个Person类 继承自NSObject,它有Name,height,age 三个属性

    .h文件

    #import <UIKit/UIKit.h>

    @interface Person : NSObject

    @property (nonatomic, copy)NSString  *name;

    @property (nonatomic, assign) CGFloat height;

    @property (nonatomic, assign) NSInteger age;

    @end

    .m文件 在.m文件中重写height的setter方法.

    #import "Person.h"

     @implementation Person

     - (void)setHeight:(CGFloat)height

    {

        _height = height;

        NSLog(@"setHeight");

    }

    @end

    2.在控制器中实例化一个person对象 ,并给它的属性赋值

    #import "ViewController.h"

    #import "Person.h"

    @interface ViewController ()

    @property (nonatomic, strong) Person *person;

    @end

    @implementation ViewController

    - (void)viewDidLoad {

        [super viewDidLoad];

        Person *person = [[Person alloc]init];

        self.person = person;

        person.name = @"xiaoming";

        person.age = 19;

         person.height = 180;

    //给person 添加一个监听者,监听它的属性 height的改变

    (注:其中forKey 和Keypath的区别是,当使用forkey的时候,只会在本类中寻找,如果没有就崩溃,如果使用keypath也会在它的子类中寻找)

        [person addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"aa"];

        person.height  = 178;

    }

     //当键值发生改变的时候就会调用

    //参数3  change  修改之后的值 或者 旧值  参数4context  附加参数

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context

    {

        NSLog(@"change = %@",change);

        

    }

     /////////////////////////////////////

    打印输出的结果

    2016-04-25 15:50:19.541 09-KVO底层实现[1147:56293] change = {

        kind = 1;

        new = 178;

        old = 180;

    }

    )

     下面说一下KVO的底层实现

    在添加KVO的时候 在运行时会添加一个当前类的子类(NSKVONotifying_Person),并重写子类的set方法,在添加监听后更改了isa指针 (isa 指针的而作用:

    调用一个类的方法 会根据 isa指针去对应的方法列表中找这个方法然后找到这个方法的实现  然后执行)把它指向了子类,当再次赋值的时候会调用子类的set方法.

    总结:

    当使用KVO时

    1.动态的创建一个叫NSKVONotifying_CZPerson  的子类

    2.更改当前类的 isa指针为子类

    3.传入一堆参数 1.监听者(将来调用observeValueForKeyPath)  2.keypath(决定了重写哪个set方法)  3.枚举(决定传哪些给你) 4.携带参数

    4.根据keypath 重写子类的set方法

    5.在子类的set方法中  根据枚举 保存所有的属性值  然后调用父类的set方法 然后调用监听者的observeValueForKeyPath... 把对应的值传出去通知监听者发生了事情

  • 相关阅读:
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 400 第N个数字
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 399 除法求值
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    Java实现 LeetCode 398 随机数索引
    linux中的cd ..和cd -命令有什么区别?
    GCC使用
  • 原文地址:https://www.cnblogs.com/relly0121/p/5431336.html
Copyright © 2011-2022 走看看