一 概念
Objective-C 中的键(key)-值(value)观察(Observer) 简称kvo
基本思想:一个目标对象管理所有依赖于它的观察者对象,并在它自身的状态改变时主动通知观察者对象。这个主动通知通常是通过调用各观察者对象所提供的接口方法来实现的。观察者模式较完美地将目标对象与观察者对象解耦。
二 涉及到的方法
//添加观察者通过键值名称去观察属性的变化
- (void)addObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath options:(NSKeyValueObservingOptions)options context:(void *)context;
//回调函数
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context;
//移除观察者对属性的监测(注意:必要要实现此方法,否则会发生资源泄漏)
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath context:(void *)context NS_AVAILABLE(10_7, 5_0);
- (void)removeObserver:(NSObject *)observer forKeyPath:(NSString *)keyPath;
NSObject,NSArray,NSSet实现了以上方法,所以不仅可以观察普通对象,还可以观察数组或集合类对象。
三 示例代码
例如有一件商品的价格是在不断的变化的,更新显示。
1 定义一个goodModel 如下代码是goodModel.m
#import "goodModel.h"
@interface goodModel()
{
//商品名称
NSString *goodsName;
//商品价格
float price;
}
@end
@implementation goodModel
@end
2 viewController.m
#import "ViewController.h"
#import "goodModel.h"
@interface ViewController ()
{
//创建一个书的对象模型
goodModel *_bookModel;
UILabel *_lable;
UIButton *_button;
}
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//示例化该模型
_bookModel = [[goodModel alloc]init];
//设置该模型的属性
[_bookModel setValue:@"book" forKey:@"goodsName"];
[_bookModel setValue:@(12.7) forKey:@"price"];
//重要步骤 当前对象作为监测者 观察price的变化
[_bookModel addObserver:self forKeyPath:@"price" options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionOld context:NULL];
//创建一个lable显示price
_lable = [[UILabel alloc]initWithFrame:CGRectMake(50, 200, 200, 50)];
_lable.backgroundColor = [UIColor grayColor];
_lable.text = [NSString stringWithFormat:@"%f",[[_bookModel valueForKey:@"price"]floatValue]];
[self.view addSubview:_lable];
//创建一个按钮,改变price的值
_button = [UIButton buttonWithType:UIButtonTypeSystem];
_button.frame = CGRectMake(100, 280, 80, 40);
_button.backgroundColor = [UIColor redColor];
[_button addTarget:self action:@selector(buttonClicked:) forControlEvents:UIControlEventTouchUpInside];
[_button setTitle:@"改价" forState:UIControlStateNormal];
[self.view addSubview:_button];
}
#pragma mark 回调函数 change字典中包括被监测属性的信息
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)contex{
NSLog(@"%@",change);
_lable.text = [NSString stringWithFormat:@"%f",[[_bookModel valueForKey:@"price"]floatValue]];
}
- (void)buttonClicked:(UIButton *)sender{
[_bookModel setValue:@(20.0) forKey:@"price"];
}
- (void)dealloc{
[_bookModel removeObserver:self forKeyPath:@"price"];
}
@end
3 模拟器界面
4 change字典打印的值
KVODemo1-0716[1607:40771] {
kind = 1;
new = 20;
old = "12.7";
}