KVO使用现有模型数据加载新视图

时间:2013-06-13 18:00:55

标签: ios model-view-controller key-value-observing

我最近开始发现KVO可以做些什么,我正在重构一些代码并同时保存很多行。我确实面临一个如此笼统的问题,它让我想知道是否推荐某种模式。

在某些情况下,我加载了一个新的视图控制器,需要表示已经初始化的模型中的数据。在-viewDidLoad我会注册KVO:

[_model addObserver:self
         forKeyPath:kSomeKey
            options:NSKeyValueObservingOptionNew
            context:(__bridge void *)(_model)];

并在值更改时更改我的界面:

 -(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
                        change:(NSDictionary *)change 
                       context:(void *)context
{
if ([keyPath isEqual:kSomeKey] && context == (__bridge void *)(_model)) {

    [self updateSomeInterfaceElement];

}

不幸的是,当我加载新视图时,视图不会使用模型中的当前值进行更新。

我是-updateSomeInterfaceElement中致电-viewDidLoad的最佳选择吗?这似乎不是一个大问题,但是当听取10-20个属性时,它看起来非常低效(特别是因为我的所有-updateSomeInterfaceElement方法大多只有1行,所以不需要将它们变成一个单独的方法)。有没有办法绕过这个,还是有更优雅的解决方案?

1 个答案:

答案 0 :(得分:1)

您想要更改选项以包含NSKeyValueObservingOptionInitial。这将导致KVO在添加观察者时触发通知,为观察者提供“初始”值。

另外,顺便说一下,如果调用observeValueForKeyPath:...来收到您未注册的通知,您应该养成调用super的习惯。此外,避免在KVO上下文中使用“实时”指针更加防范(因为如果当前对象被释放,未来的对象可能具有相同的指针。)我通常更喜欢使用这样的模式:

static void * const MyObservationContext = (void*)&MyObservationContext;

- (void)viewDidLoad
{
    // ... other stuff ...
    [self addObserver:self forKeyPath:@"model.someKey" options:NSKeyValueObservingOptionNew | NSKeyValueObservingOptionInitial context:MyObservationContext];
    // ... other stuff ...
}

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context 
{
    if (context == MyObservationContext)
    {
        // Do stuff
    }
    else
    {
        [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
}