• 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... 把对应的值传出去通知监听者发生了事情

  • 相关阅读:
    JS DOM基础
    JS 部分常见循环、分支、嵌套练习
    记一些让footer始终位于网页底部的方法
    JS 实现banner图的滚动和选择效果
    JS 部分基础内容总结
    Flex弹性布局基础教程
    My SQL数据库的安装与配置
    网页共用头部和尾部的部分方法
    Unity3d入门 关于unity工具的熟悉
    Unity3d学习 制作地形
  • 原文地址:https://www.cnblogs.com/relly0121/p/5431336.html
Copyright © 2020-2023  润新知