标签:
- (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