由NSArrayController支持的NSTableView:为什么setContent:工作而IB不工作?

时间:2011-10-30 12:47:40

标签: cocoa binding nstableview nsarraycontroller

我试图实现几乎最简单的将NSTableView绑定到NSArrayController的情况,以便NSTableView由NSArray支持。

以下是设置:

  1. 我有一个NSArrayController,其'Content Array'绑定到我的app委托中的NSArray。
  2. 在NSArrayController的'Object Controller'中,类名设置为Model,即NSArray中包含的对象类型。
  3. NSTableView的单个列的'Value'绑定到Array Controller的'arrangeObjects'的键'name',这是Model类的唯一字段。
  4. 在我的app委托的applicationDidFinishLaunching中,我初始化了NSArray,并插入了一些Model对象。
  5. 但是,与模型相对应的行不会出现在表格中,除非我也这样做:[self.arrayController setContent: self.array]

    有没有办法可以使用Interface Builder中连接的绑定来实现此功能?我原以为NSArrayController的'Content Array'直接绑定到NSArray这意味着我不必以编程方式设置内容。知道为什么会帮助我更好地理解绑定。

1 个答案:

答案 0 :(得分:13)

您的阵列控制器正在观察您的App Delegate的“数组”属性。这意味着只有在设置了数组对象时才会发送KVO通知,而不是在添加对象时发送。听起来你正在使用NSMutableArray并向其添加对象,这解释了为什么没有通知Array Controller变化,因为底层对象没有改变。

简单的解决方案是将您的调用包装在一个意愿/更改块中,如下所示:

[self willChangeValueForKey:@"array"];
[self.array addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[self.array addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];
[self didChangeValueForKey:@"array"];

这会手动通知观察者“阵列”属性发生了变化。

答案很长:你做错了。拥有数组控制器的关键在于将管理数组的工作转移到控制器类本身,因此它管理底层数组,发出正确的通知,维护状态等,而不必担心实现细节。一个更好的解决方案是解开内容数组绑定,只需将对象直接添加到数组控制器,如下所示:

[arrayController addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[arrayController addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];

这是有效的,因为数组控制器在内部管理自己的数组。

最佳解决方案是使用Core Data。 NSArrayController旨在与它一起使用。您还可以免费获得大量内容,例如persistentce,undo支持,对象关系,以及只需直接从UI控件调用阵列控制器上的add:就可以在不编写代码的情况下添加对象。