KVO

作者: gpylove | 来源:发表于2019-11-20 18:26 被阅读0次

          KVO在OC中是实现键值(key-value-observing)观察的方式,在设计模式中是典型的观察者模式, 当观察者将被观察者的某个属性设置为观察的对象时,若被观察的该属性值发生变化时,就会触发观察者对象所实现的KVO接口方法,从而达到通知观察者的目的。

        简单来说KVO可以通过监听key,来获得value的变化,用来在对象之间监听状态变化。KVO的定义都是对NSObject的扩展来实现的,Objective-C中有个显式的NSKeyValueObserving类别名,所以对于所有继承了NSObject的类型,都能使用KVO。

         KVO的实现是基于iOS runtime机制的isa-swizzling(指针替换),当一个对象的属性被注册成被观察对象时,会生成一个中间类继承自该类,然后将该类的isa指针指向新生成的子类,这样被观察的对象就变成了这个中间类,同时重写了被观察属性的setter方法,当新对象的属性发生变化时,则会依次通知注册的观察者对象。

自动KVO(默认方式)

a、添加观测者

-(void)addObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath options:(NSKeyValueObservingOptions)options context:(nullablevoid*)context;

b、当观测的属性值发生改变时调用的函数

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

c、移除观察者

- (void)removeObserver:(NSObject*)observer forKeyPath:(NSString*)keyPath context:(nullablevoid*)context;

        注意,如果被观察的属性没有调用Setter方法,而是通过直接访问其实例变量(_下划线方法)是不会触发回调的。

手动KVO

        KVO在属性发生改变的时候默认是自动调用的,如果需要手动的控制这个调用时机,那么在被观察的对象.m文件中调用如下方法:

+(BOOL)automaticallyNotifiesObserversForKey:(NSString*)key{

returnYES;//默认,自动模式

returnNO;//手动模式

}

同时在属性变化之前,调用:

-(void)willChangeValueForKey:(NSString*)key;

在属性变化之后,调用:

-(void)didChangeValueForKey:(NSString*)key;

        其实无论属性的值是否发生改变,是否调用Setter方法,只要调用了willChangeValueForKey:和didChangeValueForKey:就会触发回调。

依赖键KVO

如果在当前Person类中引入另外一个Dog类:

@interface Dog : NSObject

@property (copy, nonatomic) NSString *age;

@property (copy, nonatomic) NSString *name;

@end

那么此时我们怎么通过Person来观察Dog类的age属性呢?

[_p addObserver:self forKeyPath:@"dog.age" options:NSKeyValueObservingOptionNew    context:nil];

我们现在希望,只要Dog类中有属性的变化,就会通知到Person类,如果我们每一个属性都添加一遍观察者会很麻烦,这里就需要用到属性依赖。我们在Person类的.m中添加一个方法:

+(NSSet<NSString *> *)keyPathsForValuesAffectingValueForKey:(NSString *)key

{

    NSSet *keyPath = [super keyPathsForValuesAffectingValueForKey:key];

    if([keyisEqual:@"dog"]) {

        keyPath = [[NSSetalloc]initWithObjects:@"_dog.age",@"_dog.name",nil];

    }

    returnkeyPath;

}

同时在添加观察者时,不用对dog具体的属性添加,直接对dog进行观察。

[_p addObserver:self forKeyPath:@"dog" options:NSKeyValueObservingOptionNew context:nil];

        设置键之间的依赖关系+(NSSet<NSString*>*)keyPathsForValuesAffectingValueForKey:(NSString*)key;当添加一个被观察的keyPath,这个方法就会走。其大概意思是就是:用一组键的值去影响另一个键值。注意该方法一定要考虑非指定key时的情况要调用[super keyPathsForValuesAffectingValueForKey:key],不能影响其他的情况。

相关文章

  • 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/wyyoictx.html