标签:
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
第一个参数是观察者对象,负责处理监听事件;第二个是观察的属性的路径;第三个是观察的选项;第四个是上下文。
比如说大家都喜欢给宠物取名字,养的猫也会有名字
@interface Cat : NSObject @property (nonatomic, strong) NSString* name; @end
我们想要在猫的名字改变的时候有个通知,我们在一个viewcontroller里面做测试,其他多余的代码暂时不要
#import "KVOViewController.h" #import "Cat.h" @interface KVOViewController () @property (nonatomic, strong) Cat* whiteCat; @end @implementation KVOViewController - (void)viewDidLoad { [super viewDidLoad]; _whiteCat = [[Cat alloc] init]; _whiteCat.name = @"hello"; [_whiteCat addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil]; } - (IBAction)observerTap:(id)sender { _whiteCat.name = @"kitty"; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"name"]) { NSLog(@"white cat‘s name change"); } } @end
我们在当前进行观察的,所以第一个参数观察者是self,当然这不是固定的,可以指到其他地方观察,当都要实现监听方式。
我们是要在猫的名字改变的时候得到事件,所以监听的第二个参数keypath是name。
keypath描述的是要观察的属性,而这个属性,要符合KVC协议的,简单点说,就是这个属性要能够被进行以下操作
- (void)setValue:(id)value forKey:(NSString *)key;
就是说这个属性能够被键值编码,如果我们想观察一个数组的count属性,直接使用
[_obArr addObserver:self forKeyPath:@"count" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:nil];
程序会crash的,因为数组的count属性不符合键值编码,即简单的不能被setValue:forKey,因为它不是id类型。
keypath,顾名思义,这是一个寻找的路径,所以这里如果是想观察name的属性也是可以用点语法观察的,当然,前提也是要符合KVO协议。
最后一个参数,一般是传nil或者NULL,但作用呢,其实很强大,比如当前有两个Cat的实例,我都要观察他们的name属性变化,我该如何区分是哪个实例呢?就用这个参数,context。我们给上面的例子添加点代码:
@interface KVOViewController () @property (nonatomic, strong) Cat* whiteCat; @property (nonatomic, strong) Cat* blackCat; @end @implementation KVOViewController - (void)viewDidLoad { [super viewDidLoad]; _whiteCat = [[Cat alloc] init]; _whiteCat.name = @"hello"; [_whiteCat addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"White"]; _blackCat = [[Cat alloc] init]; _blackCat.name = @"kitty"; [_blackCat addObserver:self forKeyPath:@"name" options:NSKeyValueObservingOptionOld | NSKeyValueObservingOptionNew context:@"Black"]; } - (IBAction)observerTap:(id)sender { _whiteCat.name = @"kitty"; _blackCat.name = @"hello"; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"name"]) { id instanceObj = (__bridge id)(context); NSString* contextStr = instanceObj; if ([contextStr isEqualToString:@"White"]) { NSLog(@"white cat‘s name change"); } else if ([contextStr isEqualToString:@"Black"]) { NSLog(@"black cat‘s name change"); } } } @end
标签:
原文地址:http://my.oschina.net/u/574245/blog/530661