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

jog*_*ran 4 cocoa binding nstableview nsarraycontroller

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

这是设置:

  1. 我有一个NSArrayController,其'Content Array'绑定到我的app委托中的NSArray.
  2. 在NSArrayController的"对象控制器"中,类名设置为Model,即NSArray中包含的对象类型.
  3. NSTableView的单个列的"Value"绑定到Array Controller的'arrangeObjects'的键'name',它是Model类的唯一字段.
  4. 在我的app委托的applicationDidFinishLaunching中,我初始化了NSArray,并插入了一些Model对象.

但是,对应于Model的行不会出现在表中,除非我也这样做:[self.arrayController setContent: self.array].

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

Fra*_*rew 13

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

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

[self willChangeValueForKey:@"array"];
[self.array addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[self.array addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];
[self didChangeValueForKey:@"array"];
Run Code Online (Sandbox Code Playgroud)

这会手动通知观察者"array"属性发生了更改.

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

[arrayController addObject:[NSDictionary dictionaryWithObject:@"foo" forKey:@"name"]];
[arrayController addObject:[NSDictionary dictionaryWithObject:@"bar" forKey:@"name"]];
Run Code Online (Sandbox Code Playgroud)

这是因为数组控制器在内部管理自己的数组.

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