美文网首页
KVO的底层实现原理

KVO的底层实现原理

作者: 6ffd6634d577 | 来源:发表于2017-02-14 11:57 被阅读79次
什么是KVO ?

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

KVO的使用比较简单,基本上都是三步:

  1. 注册观察者
    addObserver:forKeyPath:options:context:
  1. 观察者中实现
    observeValueForKeyPath:ofObject:change:context:
  2. 移除观察者
    removeObserver:forKeyPath:

接下来我们通过一个小Demo来探索KVO的底层实现:

1.新建工程后创建一个Person类

#import <Foundation/Foundation.h>

@interface Person : NSObject

@property(nonatomic,copy)NSString *name;

@end
-----------------------------------------
#import "Person.h"

@implementation Person

@end

控制器里的代码如下:

#import "ViewController.h"
#import "Person.h"

@interface ViewController ()

@property(nonatomic,strong)Person *p;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    Person * p =[[Person alloc] init];
    self.p = p;
    p.name = @"张三";
    p.height = 170;
    
    //添加KVO 监控 p 当中 属性height 的改变
    [p addObserver:self forKeyPath:@"height" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:nil];
    
    p.height = 180;
}

//监控属性变化触发的方法..
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    if ([keyPath isEqualToString:@"height"]) {
        
        NSLog(@"%@",change);
        
    }
}


-(void)dealloc
{
    [self.p removeObserver:self forKeyPath:@"height"];
}

第一次在添加监听者的时候打断点p对象的isa指针如下:

4580E4B2-32C8-40C5-9B9F-CFAE21F9173F.png

再往下走一步的时候p的isa指针如下:

A30651A7-4950-4BE8-B0C3-A8D04FB82E75.png

再往下走的时候就会出发KVO的监听方法

B1F8ECED-78D1-491C-B3A4-D1F69740EFC8.png

接下来我们用setValue:forKey(KVC)方法给p的属性赋值:

//    p.height = 180;
    [p setValue:@(180) forKey:@"height"];

控制台打印结果如下:

40F329D8-BA1B-4116-9AC6-0700E4F655E6.png

接下来我们测试一下直接给p的属性赋值,不通过set方法:

在Person类中添加一个方法:
-(void)changeHeight
{
    _height = 200;
}

在控制器类中:
//    p.height = 180;
//    [p setValue:@(180) forKey:@"height"];
    [p changeHeight];

控制台没有打印任何信息,说明没有触发KVO的监听方法:

C60729A0-0111-46CA-BA73-E00C1A140751.png
总结:

可见,在addObserver:forKeyPath:options:context:之后,对象p的isa变为了NSKVONotifying_Person。
所以,根据上面的isa介绍,响应setAge的方法,实际上是对象p的isa即NSKVONotifying_Person类的setAge方法,并不是原Person类的setAge方法。
可以大胆想象,NSKVONotifying_Person类是Person类的子类,在NSKVONotifying_Person类内部,重写了setAge方法,并且在setAge方法里让监听器调用了observeValueForKeyPath:ofObject:change:context:方法。
那么,NSKVONotifying_Person是怎么产生的呢?简单的说,是由runtime产生的。

相关文章

  • Today面试

    Runloop 底层原理Kvo 底层原理ARC 底层原理 如何实现GCD 底层原理Block 底层原理Aut...

  • IOS底层(三) KVO底层实现原理

    @[TOC](IOS底层(三) KVO底层实现原理 ) 一,KVO简述 KVO的全称 Key-Value Obse...

  • iOS - KVO

    [toc] 参考 KVO KVC 【 iOS--KVO的实现原理与具体应用 】 【 IOS-详解KVO底层实现 】...

  • KVO的底层实现原理

    KVO的底层实现原理
    KVO的定义(Key-Value Observing) ...

  • iOS - 自定义KVO

    之前我们已经了解过了KVO的底层实现原理,不过呢,在我们开始实现自定义KVO之前再来简单回顾下KVO的实现原理 1...

  • iOS开发面试攻略(KVO、KVC、多线程、锁、runloop、

    KVO & KVC KVO用法和底层原理 使用方法:添加观察者,然后怎样实现监听的代理 KVO底层使用了 isa-...

  • 底层原理

    iOS底层原理总结 - Category的本质 KVO详解及底层实现青少年一定要读的KVO指南 iOS 底层解析w...

  • 2018-02-14

    探究KVO的底层实现原理 addObserver:forKeyPath:options:context:各个参数的...

  • 探究KVC的底层实现原理

    慕课网地址 以前写了关于的实现原理的文章,探究KVO的底层实现原理,现在我们也探究一下的底层实现 原理 的全称是K...

  • 关于KVO底层Runtime实现的那点事

    有很多公司iOS面试都会被问到KVO底层的实现。网上也有很多篇关于KVO的底层原理,但是都是用willChange...

网友评论

      本文标题:KVO的底层实现原理

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