kvo作用
KVO俗称键值监听,它提供一种机制,当指定的对象的属性被修改后,则对象就会接收到通知。就是每次指定的被观察的对象的属性被修改后,KVO就会自动通知想要的观察者。
使用步骤:
步骤一
给对象添加监听者
首先创建一个person类
@interface Person :NSObject
@property(nonatomic,copy) NSString *name;
@end
//在viewcontroller扩展中添加一个属性
@property(nonatomic,strong) Person *person;
//并给该属性初始化对象,并给属性添加kvo监听
self.person = [Person new];
[self.person addObserver:self forKeyPath:@"name"options:NSKeyValueObservingOptionOld|NSKeyValueObservingOptionNew context:nil];
具体参数说明:
- observer:观察者
- forkeyPath参数是一个键值对中的键,唯一标示符绑定值。
- options:
NSKeyValueObservingOptionNew:change字典包括改变后的值
NSKeyValueObservingOptionOld: change字典包括改变前的值
NSKeyValueObservingOptionInitial: 注册后立刻触发KVO通知
NSKeyValueObservingOptionPrior: 值改变前是否也要通知
- context:上下文,这个会传递到订阅者的函数中,用来区分消息,所以应当是不同的。
步骤二
如果修改了person的name的值就会触发下面方法
//需要在这里实现监听后要做的操作
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
步骤三
删除指定Key路径的监听器:
在- (void)dealloc;方法中移除监听
- (void)removeObserver:(NSObject *)anObserver forKeyPath:(NSString *)keyPath
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context
kvo原理
主要用到了运行时(runtime)
当某个类的对象第一次被观察时,会通过运行时动态地创建对应于该类的一个派生类,在这个派生类中系统会重写父类中被观察属性的setter方法。然后根据options中的值来确定触发哪些方法,下面会触发改变前和改变后的方法。
-(void)setName:(NSString *)name{
[self willChangeValueForKey:@"name"];//会在值即将发生变化时发送通知
_name = name;
[self didChangeVauleForKey:@"name"]; //会在值已经发生变化时发送通知
}
automaticallyNotifiesObserversForKey该方法用于是否自动触发kvo,返回no要手动触发,
+(BOOL)automaticallyNotifiesObserversForKey:(NSString *)key{
if([key isEqualToString:@"name"]){
return NO;
}
return [super automaticallyNotifiesObserversForKey:key];
}
应用
商城购物车中都有一个全选按钮,如果每个商品都一一勾选后,那么全选按钮就会被自动选中。如果其中一个商品没有选中,然后全选按钮不会被选中。
这里需要监听加入购物车数组对象。
@interface ViewController ()
//下单数据源
@property(nonatomic,strong) NSMutableArray *pendingDataSource;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//监听pendingDataSource对象是否发生变化
[self addObserver:self forKeyPath:@"pendingDataSource" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:nil];
}
-(void)addAction{
[[self mutableArrayValueForKey:@"pendingDataSource"] addObject:person];
}