基于键值的观察者模式编程

键值观察提供了一个机制,允许当其他对象的特定属性被修改时通知观察者对象。这一机制在应用程序的模型和控制器之间的通讯方面尤其有用。通常情况下,控制器对象观察模型对象的属性,而视图对象通过控制器观察模型对象的属性。此外,一个模型对象也可以观察其他模型对象。

要接收一个属性的键值观察通知,需要:

  • 被观察对象调用addObserver:forKeyPath:options:context:方法注册观察者对象;
  • 观察类必须实现observeValueForKeyPath:ofObject:change:context:方法。

示例

1. 新建一个Single View Application,并启用ARC;

2. 新建一个StockData类,头文件如下所示:

@interface StockData : NSObject

@property (assign, nonatomic) CGFloat price;

@end

实现代码可以先不处理;

3. 在ViewController.m中,首先修改接口定义,代码如下:

#import "StockData.h"

@interface ViewController ()
{
    StockData   *_stock;
    UILabel     *_label;
}

@end

4. 修改viewDidLoad方法如下:

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    // 1. 初始化StockData
    _stock = [[StockData alloc]init];
    
    // 2. 新建标签控件显示StockData的price属性
    _label = [[UILabel alloc]initWithFrame:CGRectMake(0, 100, 320, 40)];
    [_label setTextAlignment:NSTextAlignmentCenter];
    [self.view addSubview:_label];
    
    // 3. 添加观察者观察price属性
    [_stock addObserver:self
                  forKeyPath:@"price"
                     options:NSKeyValueObservingOptionNew
                     context:nil];
    
    // 4. 测试属性变化
    [_stock setPrice:20];
    [_stock setPrice:30];
    [_stock setPrice:40];
}

5. 实现observeValueForKeyPath:ofObject:change:context:方法,在viewDidLoad方法下方,添加如下代码:

- (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context
{
    if ([keyPath isEqual:@"price"]) {
        NSLog(@"new price is %@", change[@"new"]);
        
        [_label setText:[NSString stringWithFormat:@"%0.02f", _stock.price]];
    }
}

6. 生成并运行程序,标签中应该显示40.00,不过在控制台可以看到3次price属性的变化情况。

补充

对于本此示例,由于是支持ARC的,因此没有删除观察者的代码。但是对于复杂些的应用,在不需要时,需要删除观察者监听。要做到这一点,可以调用如下代码:

[_stock removeObserver:self forKeyPath:@"price"];

搞定收工!

 

posted @ 2013-05-28 05:01  趣味苹果开发  阅读(1927)  评论(0编辑  收藏  举报