KVO

作者: AntKing | 来源:发表于2019-04-10 09:37 被阅读0次

先来定义一个类,要被我们监听的类

  • YSPerson.h 文件

#import <Foundation/Foundation.h>

@interface YSPerson : NSObject
@property (assign, nonatomic) int age;
@end

  • YSPerson.m文件

@implementation YSPerson
{
    int _age;
}

- (void)setAge:(int)age
{
    _age = age;
}

- (int)age
{
    return _age;
}

@end

在控制器中监听YSPerson 实例对象的 age


- (void)viewDidLoad {
    [super viewDidLoad];
    
    self.person1 = [[YSPerson alloc] init];
    self.person1.age = 1;
    
    NSLog(@"person1添加KVO监听之前 - %@",
          object_getClass(self.person1));
    NSLog(@"person1添加KVO监听之前 - %p",
          [self.person1 methodForSelector:@selector(setAge:)]);

    // 给person1对象添加KVO监听
    NSKeyValueObservingOptions options = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    [self.person1 addObserver:self forKeyPath:@"age" options:options context:@"123"];

    NSLog(@"person1添加KVO监听之后 - %@",
          object_getClass(self.person1));
    NSLog(@"person1添加KVO监听之后 - %p ",
          [self.person1 methodForSelector:@selector(setAge:)]);


  /*
  通过上面的打印输出,可以证明,监听前后的实例对象的类型和
  setAge的方法地址都是不一样的,验证了我们的猜想
*/

}


- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//    self.person1.age = 21;

    // NSKVONotifying_YSPerson是使用Runtime动态创建的一个类,是YSPerson的子类
    // self.person1.isa == NSKVONotifying_YSPerson
    [self.person1 setAge:21];
    
}


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

// 当监听对象的属性值发生改变时,就会调用
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
{
    NSLog(@"监听到%@的%@属性值改变了 - %@ - %@", object, keyPath, change, context);
}

  • 当我们点击屏幕的时候,给self.person1的age赋值 21时候,我们就能监听到值的改变

  • 实现原理是利用Runtime来完成

  • 当我们监听了YSPerson的属性的时候,系统会在Runtime阶段为我们创建一个NSKVONotifying_YSPerson ,这个类继承自YSPerson

  • 在NSKVONotifying_YSPerson的实现中插入了以下代码

@implementation NSKVONotifying_YSPerson

- (void)setAge:(int)age
{
    _NSSetIntValueAndNotify();
}

// 伪代码
void _NSSetIntValueAndNotify()
{
    [self willChangeValueForKey:@"age"];
    [super setAge:age];
    [self didChangeValueForKey:@"age"];
}

- (void)didChangeValueForKey:(NSString *)key
{
    // 通知监听器,某某属性值发生了改变
    [oberser observeValueForKeyPath:key ofObject:self change:nil context:nil];
}

@end


  • 并将NSKVONotifying_YSPerson的 class 方法,所以在我们调用[self.person1 class] 方法的时候返回的还是YSPerson

相关文章

  • iOS原理篇(一): KVO实现原理

    KVO实现原理 什么是 KVO KVO 基本使用 KVO 的本质 总结 一 、 什么是KVO KVO(Key-Va...

  • 04. KVO使用,原理,本质

    问题 KVO日常使用 KVO原理(KVO本质是什么) 如何手动触发KVO 直接修改成员变量会触发KVO吗 KVO图...

  • 20.iOS底层学习之KVO 原理

    本篇提纲1、KVO简介;2、KVO的使用;3、KVO的一些细节;4、KVO的底层原理; KVO简介 KVO全称Ke...

  • 深入理解KVO

    iOS | KVO | Objective-C KVO的本质是什么,如何手动触发KVO? 1.什么是KVO KVO...

  • OC语法:KVO的底层实现

    一、KVO是什么二、怎么使用KVO三、KVO的底层实现四、KVO常见面试题 一、KVO是什么 KVO全称Key-V...

  • KVO基本使用

    分三部分解释KVO一.KVO基本使用二.KVO原理解析三.自定义实现KVO 一、KVO基本使用 使用KVO,能够非...

  • KVO 解析

    KVO解析(一) —— 基本了解KVO解析(二) —— 一个简单的KVO实现KVO解析(三) —— KVO合规性K...

  • KVO

    目录 1. KVO的使用1.1 KVO基本使用方法1.2 KVO手动触发模式1.3 KVO属性依赖1.4 KVO容...

  • OC语言之KVO与KVC

    KVO 什么是KVO? KVO 是 Key-value observing(键值观察)的缩写。 KVO是Objec...

  • 可能碰到的iOS笔试面试题(7)--KVO-KVC

    KVC-KVO KVC的底层实现? KVO的底层实现? 什么是KVO和KVC? KVO的缺陷? KVO是一个对象能...

网友评论

      本文标题:KVO

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