在其属性(模型)更改时更新UIView子类

时间:2013-04-09 23:52:43

标签: objective-c uiview subclass key-value-observing

我有一个UIView子类CustomView,它有一个属性CustomObject *model,以及一些IBOutlet属性。 CustomObject有两个属性,NSString *titleNSString *imageName。当CustomView中的任何内容发生变化时,我想要一种简单,可扩展的方式来更新model的各种渠道。我觉得应该有一些简单的方法来使用KVO,但由于可以将新对象分配给model,我不能只订阅这些通知。

我可以想到一种方法(我之前使用过)是覆盖- (void)setModel:(CustomObject *)model来重做我的布局并重新订阅该对象的KVO键。这是最合理的解决方案,还是我忽略了一些明显的解决方案?

3 个答案:

答案 0 :(得分:0)

让View控制属性与MVC设计相悖,尽管这可能会让事情变得更加艰难。我建议您创建一个ViewController自定义子类,并让它通过许多不同的方法将信息传递给视图,其中一个方法是委托/ protocool赋值,另一个是通知。

答案 1 :(得分:0)

在我读完你的问题之前,我打算建议KVO,所以,在你的问题结束时,我不得不说,是的,这正是KVO的用途。但我同意另一个答案(来自Pinwheeler) - 它不是应该进行观察的视图,而是视图控制器。

但是,如果可能,视图控制器更常用于管理模型和视图。既然它负责两者,它不需要观察任何东西;它知道模型是否因为改变了模型而改变了。

答案 2 :(得分:0)

我通过覆盖setModel:来处理这个问题:

- (void)setModel:(Model *)model {
    if (model != _model) {
        [self disconnectFromModel];
        _model = model;
        [self connectToModel];
    }
}

并在dealloc我也打电话给disconnect

- (void)dealloc {
    [self disconnectFromModel];
}

connect中,我建立了与模型的连接,如果我有,我会将模型(或模型的某些部分)传递给我的子视图(如果适用)。例如:

- (void)connectToModel {
    if (_model) {
        // Maybe start KVO...
        [_model addObserver:self forKeyPath:@"name"
            options:NSKeyValueObservingOptionInitial context:&MyKVOContext];

        // Or maybe register for notifications...
        nameNotificationObserver = [[NSNotificationCenter defaultCenter]
            addObserverForName:ModelNameDidChangeNotification object:_model queue:nil
            usingBlock:^(NSNotification *note) {
                [self modelNameDidChange];
            }];

        // Maybe pass part of the model down to a subview...
        [self.addressView setModel:model.address];
    }
}

disconnect中,我只是撤消我在connect中所做的事情:

- (void)disconnectFromModel {
    if (_model) {
        [_model removeObserver:self forKeyPath:@"name" context:&MyKVOContext];

        [[NSNotificationCenter defaultCenter] removeObserver:nameNotificationObserver];
        nameNotificationObserver = nil;

        [self.addressView setModel:nil];
    }
}

请注意,如果您确实有观察模型的子视图,则模型的更改会在两次传递中发生。首先,整个视图层次结构与旧模型断开连接。然后整个视图层次结构连接到新模型。