我认为我有一个NSTextField
。它的值绑定到我的控制器中的NSNumber *number
。控制器只需调用模型(value
)即可获得适当的值。
// In the controller
- (NSNumber *)number {
return [NSNumber numberWithFloat:[model value]];
}
- (void)setNumber:(NSNumber *)aNumber {
[model setValue:[aNumber floatValue]];
}
这很好,只有控制器不会收到模型更改的通知,因此,更改模型中的值不会更新NSTextField
。
我能想到的唯一其他选择是让模型通知控制器,控制器通过Outlet手动更新视图。但这规避了约束力。
// In the model, after value change
[[NSNotificationCenter defaultCenter] postNotificationName:@"ValueChanged" object:self];
// In the controller, after being notified
- (void)updateView:(NSNotification *)aNotification {
[myTextField setFloatValue:[model value]];
}
是否有更好的,具有绑定感知的方式来实现此通信?
答案 0 :(得分:2)
在您的控制器中,覆盖keyPathsForValuesAffectingValueForKey:类方法。类似的东西:
+(NSSet*) keyPathsForValuesAffectingValueForKey:(NSString*)key
{
if([key isEqual:@"number"])
return [NSSet setWithObject:@"model.value"];
return [NSSet set];
}
(我不在我的Mac上,所以这是未经测试的;但一般的想法应该是合理的)
答案 1 :(得分:2)
另一个选择(以及我通常自己做的,纯粹是出于个人喜好)就像(在控制器中):
-(void)setModel:(id)m
{
[model removeObserver:self forKeyPath:@"value"];
[m retain];
[model release];
model = m;
[model addObserver:(self) forKeyPath:@"value" options:NSKeyValueObservingOptionNew context:NULL];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if([keyPath isEqual:@"value"])
{
[self willChangeValueForKey:@"number"];
[self didChangeValueForKey:@"number"];
}
}
同样,这段代码未经测试,但总体思路应该有效。
答案 2 :(得分:1)
我的视图中有一个NSTextField。它的值绑定到我的控制器中的NSNumber *号。控制器只需调用模型(值)即可获得适当的值。
为什么此属性将值包装在NSNumber中? KVC会将原始值(例如float
)转换为对象和从对象转换。
这很好,只有控制器不会收到模型更改的通知,因此,更改模型中的值不会更新NSTextField。
模型更改与此处无关,并且控制器不需要知道模型属性更改的值,除非控制器正在观察该属性 - 在这种情况下,控制器是收到有关这些更改的通知,因为您正在使用模型的属性访问器。
问题是你没有通过模型绑定文本字段 - 而是将它绑定到控制器上的假属性。
因此,假设控制器已公开模型对象的属性,只需使用关键路径model.value
将文本字段绑定到控制器。