A、概要
iOS 开发有多种设计模式,其中就有一种叫做观察者模式,它是通过 KVO 实现的。
B、KVO 简介
KVO 的全称是 Key-Value Observing,是ObjC中原生支持的一种机制。
C、KVO 实现原理
当对一个对象添加观察者,被观察对象的属性值发生变化时,观察者会得到通知,并对变化做出相应的处理。
D、KVO 的特点
1. 支持多个观察者观察同一属性,也支持一个观察者监听不同属性。
2. 利用它可以很容易地实现视图和数据模型的分离,当数据模型的属性值改变之后,作为监听器的视图就会被激发,并回调监听器自身的监听方法。
3. 对于KVC的基本的方法都定义在 NSKeyValueCoding 的非正式协议中,并且NSObject默认实现了该协议。相对的,在ObjC中要实现KVO则必须实现
NSKeyValueObServing 协议,不过 NSObject 已经实现了该协议,因此几乎所有的ObjC对象都可以使用KVO。
E、在 ObjC 中 KVO 的用法
注册观察者:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
实现回调监听方法:
- (void)observeValueForKeyPath:(nullable NSString *)keyPath ofObject:(nullable id)object change:(nullable NSDictionary<NSString*, id> *)change context:(nullable void *)context;
移除观察者:
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
G、KVO 的底层实现:
1. KVO 的底层实现是通过Objective-C强大的运行时(runtime)实现的。
2. 当你第一次观察一个对象object时,runtime 会动态被创建一个继承自该对象object所属类的子类,类名格式为为NSKVONotifying_[subclass名],同时保存注册
观察者方法中的所有参数,包括监听者、路径、枚举、携带参数等。
3. 这个新创建的子类重写了所有被观察属性的 setter 方法,并且在内部给观察者发送通知,通知所有观察对象值的更改。
4. 最后把这个对象object的 isa 指针 ( isa 指针告诉 Runtime 系统这个对象的类是什么类型的 ) 指向这个新创建的子类,此时这个被观察的对象 object 就神奇地变
成了新的子类的实例。
H、Demo验证:
<span style="font-size:12px;">@interface People : NSObject
@property (nonatomic,strong) NSString *name;
@end</span>
<span style="font-size:12px;">#import "ViewController.h"
#import "People.h"
@interface ViewController ()
@property (nonatomic,strong) People *p;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
People *person = [[People alloc] init];
person.name = @"花无缺";
self.p = person;
[person addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
person.name = @"小鱼儿";
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"%@",change);
}
-(void)dealloc{
[self.p removeObserver:self forKeyPath:@"name"];
}
@end</span>
当第一次添加观察者对象之后,isa 指针指向了新的类,NSKVONotifying_People