Key-Value Observing (简写为KVO):当指定的对象的属性被修改了,允许对象接受到通知的机制。每次指定的被观察对象的属性被修改的时候,KVO都会自动的去通知相应的观察者。
(这样的机制听起来类 似Notification,但是notification是需要一个发送notification的对象,一般是 notificationCenter,来通知观察者。而kvo是直接通知到观察对象。)
适用kvo时,通常遵循如下流程:
1 注册:
-
(
void
)addObserver:(NSObject
*
)anObserver forKeyPath:(NSString
*
)keyPath options:(NSKeyValueObservingOptio ns)options context:(
void
*
)context
keyPath就是要观察的属性值,options给你观察键值变化的选择,而context方便传输你需要的数据(注意这是一个void型)
2 实现变化方法:
-
(
void
) observeValueForKeyPath:(NSString
*
)keyPath ofObject:(id)
object
change:(NSDictionary * )change context:( void * )context
change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。
change:(NSDictionary * )change context:( void * )context
change里存储了一些变化的数据,比如变化前的数据,变化后的数据;如果注册时context不为空,这里context就能接收到。
假设一个场景,股票的价格显示在当前屏幕上,当股票价格更改的时候,实时显示更新其价格。
1.定义DataModel,
- @interface
StockData : NSObject { -
NSString * stockName; -
float price; - }
- @end
- @implementation
StockData - @end
2.定义此model为Controller的属性,实例化它,监听它的属性,并显示在当前的View里边
- -
(void)viewDidLoad - {
-
[super viewDidLoad]; -
-
stockForKVO = [[StockData alloc] init]; -
[stockForKVO setValue:@"searph" forKey:@"stockName"]; -
[stockForKVO setValue:@"10.0" forKey:@"price"]; -
[stockForKVO addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptio nNew|NSKeyValueObservingOptio nOld context:NULL]; -
-
myLabel = [[UILabel alloc]initWithFrame:CGRectMake(100, 100, 100, 30 )]; -
myLabel.textColor = [UIColor redColor]; -
myLabel.text = [stockForKVO valueForKey:@"price"]; -
[self.view addSubview:myLabel]; -
-
UIButton * b = [UIButton buttonWithType:UIButtonTypeRoundedRect]; -
b.frame = CGRectMake(0, 0, 100, 30); -
[b addTarget:self action:@selector(buttonAction) forControlEvents:UIControlEventTouchUpIns ide]; -
[self.view addSubview:b]; -
- }
3.当点击button的时候,调用buttonAction方法,修改对象的属性
- -(void)
buttonAction - {
-
[stockForKVO setValue:@"20.0" forKey:@"price"]; - }
4. 实现回调方法
- -(void)observeValueForKeyPath:(NSString
*)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context - {
-
if([keyPath isEqualToString:@"price"]) -
{ -
myLabel.text = [stockForKVO valueForKey:@"price"]; -
} - }
5.增加观察与取消观察是成对出现的,所以需要在最后的时候,移除观察者
- -
(void)dealloc - {
-
[super dealloc]; -
[stockForKVO removeObserver:self forKeyPath:@"price"]; -
[stockForKVO release]; - }