分三部分解释KVO
一.KVO基本使用
二.KVO原理解析
三.自定义实现KVO
一、KVO基本使用
使用KVO,能够非常便捷的实现UI的更新。主要步骤分为三部分:
1.添加观察者
2.dealloc中移除观察者
3.增加回调方法
1.添加观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
以上则为添加观察者的API。
observer
:观察者(要观察属性变化的对象)
keyPath
:要监听的属性
options
:决定回调方法的回调时机以及返回的参数(后面会说)
context
:可以用来传值,不过一般传nil即可
keyPath
可以是对象的直接的属性,比如_person
的age
属性
当对象的某个属性为对象时,要监听对象属性其中的一个属性,比如person
有个属性是dog
(对象),现在要监听dog
的name
属性,keyPath就可以写成dog.name
options
typedef NS_OPTIONS(NSUInteger, NSKeyValueObservingOptions) {
//当值改变后只获取新值
NSKeyValueObservingOptionNew = 0x01,
//值改变后只获取旧值
NSKeyValueObservingOptionOld = 0x02,
//添加观察者后,立即触发一次
NSKeyValueObservingOptionInitial API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 0x04,
//变化前触发一次,变化后触发一次
NSKeyValueObservingOptionPrior API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) = 0x08
};
NSKeyValueObservingOptionNew、NSKeyValueObservingOptionOld影响值的获取
NSKeyValueObservingOptionInitial、NSKeyValueObservingOptionPrior影响回调的时机
根据需求,可以使用"|"进行组合使用
- NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld:触发时,同时返回新值以及旧值
- NSKeyValueObservingOptionInitial | NSKeyValueObservingOptionNew:初始化时触发一次,并且返回新值
...
示例:
[_person addObserver:self forKeyPath:NSStringFromSelector(@selector(age)) options:(NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld) context:nil];
self
表示所属的controller(例子中是在controller添加的观察者)
NSStringFromSelector(@selector(age))
表示要监听的是_person
对象的age
属性,也可以直接写成@"age "
NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld
表示为当值修改之后返回新值以及旧值
2.dealloc中移除观察者
注:添加和移除方法要一一对应,否则会导致crash
要在- (void)dealloc;
中调用如下的api,移除观察者
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
observer
:即为之前添加的观察者,在示例中即为self
keyPath
: 即为之前添加的要观察的属性,在示例中即为age
示例:
- (void)dealloc {
[_person removeObserver:self forKeyPath:@"age"];
}
3.增加回调方法
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context;
keyPath
:即为要观察的属性
object
:即为要观察的对象
context
:即为添加观察者时赋的值
change
:要观察的属性的值,是个字典可能会有四个key:old
、new
、kind
、notificationIsPrior
。new
表示新值所对应的key,old
表示旧值所对应的key,notificationIsPrior
表示在值改变之前触发,kind
表示回调触发的方式:
typedef NS_ENUM(NSUInteger, NSKeyValueChange) {
NSKeyValueChangeSetting = 1, //设置
NSKeyValueChangeInsertion = 2,//插入
NSKeyValueChangeRemoval = 3,//移除
NSKeyValueChangeReplacement = 4,//替换
};
change
示例
{
kind = 1; //表明是设置时触发
new = 1;//新值为1
old = 0;//旧值为0
}
当添加观察者时,options
设置为NSKeyValueObservingOptionPrior
时,会出现键值对notificationIsPrior = 1
,表示此次回调是在值修改之前触发的
{
kind = 1;
notificationIsPrior = 1; //表明此次回调是值修改之前触发的
old = 0;
}
先写到这里,有时间我会完成后面的两部分。
网友评论