我有一个UIView子类CustomView
,它有一个属性CustomObject *model
,以及一些IBOutlet
属性。 CustomObject
有两个属性,NSString *title
和NSString *imageName
。当CustomView
中的任何内容发生变化时,我想要一种简单,可扩展的方式来更新model
的各种渠道。我觉得应该有一些简单的方法来使用KVO,但由于可以将新对象分配给model
,我不能只订阅这些通知。
我可以想到一种方法(我之前使用过)是覆盖- (void)setModel:(CustomObject *)model
来重做我的布局并重新订阅该对象的KVO键。这是最合理的解决方案,还是我忽略了一些明显的解决方案?
答案 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];
}
}
请注意,如果您确实有观察模型的子视图,则模型的更改会在两次传递中发生。首先,整个视图层次结构与旧模型断开连接。然后整个视图层次结构连接到新模型。