基本概念
键值观察是一种使对象获取其他对象的特定属性变化的通知机制。
控制器层的绑定技术就是严重依赖键值观察获得模型层和控制器层的变化通知的,对于不依赖控制器层类的应用程序,键值观察提供了一种简化的方法实现检查器并更新用户的界面值。
与NSNotification不同,键值观察并没用所谓的中心对象来为所有观察者提供变化通知。取而代之的,当有变化发生时,通知被直接发送至处于观察状态的对象,NSObject提供这种基础的键值观察方法。
你可以观察任意对象的属性,包括简单属性,对一或对多关系。对多关系的观察者将会被告知发生变化的类型,也就是任意发生变化的对象。
键值观察为所有对象提供自动观察兼容性。可以通过禁用自动观察通知并实现手动通知来筛选通知。
注册观察者
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
为了正确接受属性的变更通知,观察对象必须首先发送一个addObserver:消息至被观察对象,用以传送观察对象和需要观察的属性的关键路径,以便与其注册。选项参数指定了发送变更通知时提供给观察者的信息,使用NSKeyVakueObservingOptionOld可以将初始对象值以变更字典中的一个项的形式提供给观察者,NSKeyVakueObservingOptionNew可以将新的值以一个项的形式添加至变更字典。你可以使用“ | ”将他们合在一起。
移除观察者身份
使用removeObserver:forKeyPath:消息至被观察的对象,来移除一个键值观察者。
示例代码:
Time.h
#import <Foundation/Foundation.h> @interface Time : NSObject @property(nonatomic,assign)NSInteger a; -(id)init; @end
Time.m
#import "Time.h" @implementation Time -(id)init{ if (self = [super init]) { _a = 10; [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(reduce) userInfo:nil repeats:YES]; } return self; } -(void)reduce{ self.a --;//只能使用点语法和KVC方法 // _a --;//不能使用这种方法,否则无法监听 } @end
Observer.h
#import <Foundation/Foundation.h> #import "Time.h" @interface Observer : NSObject @property(nonatomic,retain)Time *time; -(id)initWith:(id)classs; @end
Observer.m
#import "Observer.h" @implementation Observer -(id)initWith:(id)classs{ if (self = [super init]) { _time = classs; [_time addObserver:self forKeyPath:@"a" options:NSKeyValueObservingOptionNew context:nil]; } return self; } -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context{ NSLog(@"%@",change); } @end
main.m
#import <Foundation/Foundation.h> #import "Time.h" #import "Observer.h" int main(int argc, const char * argv[]) { @autoreleasepool { // insert code here... NSLog(@"Hello, World!"); Time *time = [[Time alloc]init]; Observer *ob = [[Observer alloc]initWith:time]; [[NSRunLoop currentRunLoop]run]; } return 0; }
运行结果:
2014-01-02 21:37:25.796 KVO[2297:303] Hello, World! 2014-01-02 21:37:26.803 KVO[2297:303] { kind = 1; new = 9; } 2014-01-02 21:37:27.799 KVO[2297:303] { kind = 1; new = 8; } 2014-01-02 21:37:28.797 KVO[2297:303] { kind = 1; new = 7; } 2014-01-02 21:37:29.798 KVO[2297:303] { kind = 1; new = 6; } 2014-01-02 21:37:30.798 KVO[2297:303] { kind = 1; new = 5; }
//这个会一直递减下去。。。