如何通过Controller将模型连接到使用绑定查看?

时间:2010-03-17 13:17:28

标签: objective-c cocoa model-view-controller binding

我认为我有一个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]];
}

是否有更好的,具有绑定感知的方式来实现此通信?

3 个答案:

答案 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将文本字段绑定到控制器。