要实现自动的键值观察,可以很简单的几行代码就能实现该功能:
程序功能描述:
建立一个Observer(观察者)类以及一个Target(被观察者)类,通过Observer类实例对象观察Target实例对象的Age属性!也就是说,
当age的值发生变化时,Observer实例对象应该能收到通知。
代码:
1.Target.h 和Target.m文件
// // Target.h // AutoKVO // // Created by fenglh on 14-7-31. // Copyright (c) 2014年 yons. All rights reserved. // #import <Foundation/Foundation.h> @interface Target : NSObject @property int age; // for auto KVO @end
// // Target.m // AutoKVO // // Created by fenglh on 14-7-31. // Copyright (c) 2014年 yons. All rights reserved. // #import "Target.h" @implementation Target @synthesize age; // for auto KVO @endTarget类,就这么简单的定义,可以看出来,它只声明了和定义一个age变量!注意,它是用@property 和@systhesize 两个关键字来声明和定义的!!
2.Observer.h 和 Observer.m文件
// // Observer.h // AutoKVO // // Created by fenglh on 14-7-31. // Copyright (c) 2014年 yons. All rights reserved. // #import <Foundation/Foundation.h> @interface Observer : NSObject @end
// // Observer.m // AutoKVO // // Created by fenglh on 14-7-31. // Copyright (c) 2014年 yons. All rights reserved. // #import "Observer.h" @implementation Observer - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([keyPath isEqualToString:@"age"]) { Class classInfo = context; NSString *className = [classInfo class]; NSLog(@" >> class : [%@] , Age changed", className); NSLog(@" >> old age is %@", [change objectForKey:@"old"]); NSLog(@" >> old age is %@", [change objectForKey:@"new"]); } else { [super observeValueForKeyPath:keyPath ofObject:object change:change context:context]; } } @end
3. main.m 文件
// // main.m // AutoKVO // // Created by fenglh on 14-7-31. // Copyright (c) 2014年 yons. All rights reserved. // #import <Foundation/Foundation.h> #import "Observer.h" #import "Target.h" int main(int argc, const char * argv[]) { @autoreleasepool { Observer *observer = [[[Observer alloc] init] autorelease]; Target * target = [[[Target alloc] init] autorelease]; [target addObserver:observer forKeyPath:@"age" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionOld context:[Target class]]; [target setAge:500]; [target removeObserver:observer forKeyPath:@"age"]; } return 0; }
1)将观察者和被观察者注册,即addObserver函数,为消息接收者添加观察者。
2)使用setAge这种默认访问方法来改变写值。
3)解除注册removeObserver (不调用该方法,编译器会打印出一堆信息说,你的KVO还在注册)
4.小结:
实现自动的键值观察(KVO)的要素:
1) age的声明和定义必须要用@property和@synthesize; //
2)观察者类要实现observeValueForKeyPath 方法来接受处理变更的通知
3)将观察者和被观察者注册,如[target addObserver:...] ,
4)使用默认的属性访问方法来改写属性的值,如[target setAge:500];
5)解除注册。
6. 其他
想了解手动的KVO以及为什么自动的KVO要这样实现,可以看下面的参考文章。
参考文章:
[深入浅出Cocoa]详解键值观察(KVO)及其实现机理 (讲得很详细)
KVO键-值观察编程指南