KVO
什么是KVO呢?怎么使用呢?KVO(key-value-observing)是一种监听回调机制,某一个对象注册监听后,当这个对象发生了改变,就会发送一个通知给监听者,监听者的响应方法就会被唤起,从而执行回调操作。
这里先给大家说明一下它的使用方法(就三个方法,掌握了就是干货):
1.添加观察者:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(nullable void *)context;
2.响应的方法:
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context
3.移除观察者:
-(void)removeObserver:(NSObject *) forKeyPath:(NSString *)
参数使用方法:
object : 被观察对象
observer: 观察对象
forKeyPath:被观察对象的属性名(添加观察者和响应方法中的forKeyPath是一一对应的)
options: 有4个值,分别是:
NSKeyValueObservingOptionNew 响应方法显示更改后的数据
NSKeyValueObservingOptionOld 响应方法显示更改前的数据
NSKeyValueObservingOptionInitial 把初始化的值提供给处理方法,一旦注册,立马就会调用一次。通常它会带有新值,而不会带有旧值。
NSKeyValueObservingOptionPrior 分2次调用。在值改变之前和值改变之后。
context: 任何类型参数
接下来我给大家举一个简单的例子,首先我们先生成一个Person类
@interface ViewController ()
/* Person */
@property (nonatomic, strong) Person *person;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//初始化Person类
self.person = [[Person alloc] init];
self.person.age = 0;
//对person中的age属性进行KVO监听
[self.person addObserver:self forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
//person中age发生变化,通知响应方法被调用
self.person.age = 2;
}
//通知的响应方法
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context {
NSLog(@"\n keyPath:%@ \n object: %@ \n change:%@ \n context:%@", keyPath, object, change, context);
}
//控制器被销毁后,移除观察者
-(void)dealloc {
[self.person removeObserver:self forKeyPath:@"age"];
}
这里就很明显,当self.person.age = 2这一行代码执行之后,通知就会发送,响应方法就会被调用。打印的参数如下:
keyPath:age
object: <Person: 0x60000000bbf0>
change:{
kind = 1;
new = 2;
old = 0;
}
context:(null)
这就很简单了,不用解释了吧,哈哈哈。
以下是罗列的KVO的优缺点,大家在使用时一定要了解到:
优点:
1.能够提供一种简单的方法实现两个对象间的同步。例如:model和view之间同步;
2.能够对非我们创建的对象,即内部对象的状态改变作出响应,而且不需要改变内部对象(SKD对象)的实现;
3.能够提供观察的属性的最新值以及先前值;
4.用key paths来观察属性,因此也可以观察嵌套对象;
5.完成了对观察对象的抽象,因为不需要额外的代码来允许观察值能够被观察
缺点:
1.我们观察的属性必须使用strings来定义。因此在编译器不会出现警告以及检查;
2.对属性重构将导致我们的观察代码不再可用;
3.复杂的“IF”语句要求对象正在观察多个值。这是因为所有的观察代码通过一个方法来指向;
4.当释放观察者时不需要移除观察者。
网友评论