iOS KVO

作者: 小子难缠 | 来源:发表于2022-03-12 19:06 被阅读0次

什么是KVO

  • KVO俗称“键值监听”,用来监听某个对象属性值的改变

KVO的使用

- (void)viewDidLoad {
    [super viewDidLoad];
    self.person1 = [[GMPerson alloc] init];
    self.person1.height = 160;
    self.person1.name = @"GM";
    
    NSKeyValueObservingOptions option = NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld;
    /**
     * Observer: 观察者
     * forKeyPath: 需要观察的属性
     * options: 有4个值 分别是:
     *    NSKeyValueObservingOptionNew 更改后的值,提供给处理方法
     *    NSKeyValueObservingOptionOld 更改前的值,提供给处理方法
     *    NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值
     *    NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后
     * context: 可以带入一些自定义参数
     */
    [self.person1 addObserver:self forKeyPath:@"name" options:option context:@"123"];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
//    self.person1.height = 175;
    self.person1.name = @"GMhaha";
}
- (void)dealloc{
    [self.person1 removeObserver:self forKeyPath:@"name"];
}

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

KVO 本质

在给某个对象添加KVO监听时,程序会使用Runtime动态创建一个类,例如:以上代码,我们要给 self.person1 这个对象添加KVO,在注册监听时,系统会使用Runtime动态的创建一个GMPerson的子类 NSKVONotifying_GMPerson。self.person1 这个对象的isa指针,指向 NSKVONotifying_GMPerson 这个子类,在我们改变person1里面的属性值时,会调用 NSKVONotifying_GMPerson 这个子类里的 set方法。NSKVONotifying_GMPerson 类里的set方法会调用Foundation框架里的 _NSSetIntValueAndNotify(根据具体属性类型调用。比如:float 类型会调用_NSSetFloatValueAndNotify) 这个C语言方法 这个方法里面实际上又调用了 willChangeValueForKey、set方法、didChangeValueForKey 方法,didChangeValueForKey方法里实际上是调用了通知监听器的方法。

NSKVONotifying_GMPerson 类具体实现的伪代码如下:

//
//  NSKVONotifying_GMPerson.m
//  KVO
//
//  Created by G_M on 2022/2/10.
//

#import "NSKVONotifying_GMPerson.h"

@implementation NSKVONotifying_GMPerson

- (void)setHeight:(int)height{
    _NSSetIntValueAndNotify();
}

/** 伪代码,具体实现苹果未开源 */
void _NSSetIntValueAndNotify(){
    [self willChangeValueForKey:@"height"];
    [super setHeight:height];
    [self didChangeValueForKey:@"height"];
}

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

@end

这些都是苹果动态生成的,并不需要我们自己编写,写出来只是为了帮助理解KVO的本质。

相关文章

网友评论

      本文标题:iOS KVO

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