0

我最近开始发现 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 行,所以没必要把它们做成单独的方法)。有什么办法可以规避这个问题,还是有更优雅的解决方案?

4

1 回答 1

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];
    }
}
于 2013-06-17T13:20:20.233 回答