KVO 键值监听:当我想知道一个对象的属性是否发生改变的时候 做出响应,就需要添加监听
keypath 和 key的区别
keypath会自动寻找子类的属性
key只会寻找当前类的属性
添加键值监听
[person addObserver:self forKeyPath:@“属性” options:。。。。.]
当键值发生改变的时候调用
-(void)obserValueForKeyPath:(NSString )
底层实现:运行的时候 创建一个当前类的子类,重写子类的set方法
系统 建立了一个子类,然后更改isa指针,调用一个类的方法,会根据isa指针去对应的方法列表中找到这个方法然后找到这个方法的实现,然后执行
做了哪些事情
1.动态创建了一个叫。。。的子类
2.更改之前类的isa指针为子类
3.传入一堆参数1.监听者 (将来调用observeValueForKeyPath) 2.keypath(决定了重写哪个set方法) 3.枚举(决定传哪些给你)4.携带参数
4.根据keypath重写子类的set方法
5.在子类的set方法中,根据枚举保存所有的属性值,然后调用父类的set方法 然后 用监听者的observeValueForKeyPath。。。把对应的值传出去通知
在 Objective-C 中如何实现 KVO
注册观察者(注意:观察者和被观察者不会被保留也不会被释放)
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath
options:(NSKeyValueObservingOptions)options
context:(void *)context;
接收变更通知
- (void)observeValueForKeyPath:(NSString *)keyPath
ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
移除对象的观察者身份
- (void)removeObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath;
KVO中谁要监听谁注册,然后对响应进行处理,使得观察者与被观察者完全解耦。KVO只检测类中的属性,并且属性名都是通过NSString来查找,编译器不会检错和补全,全部取决于自己。
#import "ViewController.h"
#import "CZPerson.h"
@interface ViewController ()
@property(nonatomic,strong)CZPerson *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CZPerson *person = [[CZPerson alloc]init];
self.person = person;
person.name = @"奉孝";
person.age = 25;
person.height = 181;
[person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:@"1111"];
person.age = 18;
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
NSLog(@"change = %@",change);
}
- (void)removeObserver:(NSObject *)observer
forKeyPath:(NSString *)keyPath{
[self.person removeObserver:self forKeyPath:@"height"];
}