由 NSArrayController 支持的 NSTableView:为什么 setContent: 可以工作,而 IB 却不能?

发布于 2024-12-12 09:14:10 字数 637 浏览 0 评论 0原文

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

设置如下:

  1. 我有一个 NSArrayController,其“内容数组”绑定到我的应用程序委托中的 NSArray。
  2. 在 NSArrayController 的“对象控制器”中,类名设置为 Model,即 NSArray 中包含的对象类型。
  3. NSTableView 的单列的“Value”绑定到数组控制器的“arrangedObjects”的键“name”,这是 Model 类的唯一字段。
  4. 在我的应用程序委托的 applicationDidFinishLaunching: 中,我初始化 NSArray,并插入一些 Model 对象。

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

有没有办法可以使用 Interface Builder 中的绑定来使其工作?我本来期望 NSArrayController 的“内容数组”直接绑定到 NSArray,这意味着我不必以编程方式设置内容。知道为什么会帮助我更好地理解绑定。

I am trying to implement pretty much the simplest case of binding a NSTableView to a NSArrayController, so that the NSTableView is backed by an NSArray.

Here is the setup:

  1. I have an NSArrayController whose 'Content Array' is bound to an NSArray in my app delegate.
  2. In 'Object Controller' of the NSArrayController, the class name is set to Model, the type of objects contained in the NSArray.
  3. The 'Value' of the single column of the NSTableView is bound to key 'name' of 'arrangedObjects' of the Array Controller, which is the only field of the Model class.
  4. In applicationDidFinishLaunching: of my app delegate, I initialise the NSArray, and insert some Model objects.

However, the rows corresponding to Model do not appear in the table unless I also do: [self.arrayController setContent: self.array].

Is there a way I can get this to work using bindings wired up in Interface Builder? I would have expected the fact that the NSArrayController's 'Content Array' is bound directly to the NSArray to mean that I wouldn't have to set the content programmatically. Knowing why would help me understand bindings better.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

余生一个溪 2024-12-19 09:14:11

您的数组控制器正在观察您的应用程序委托的“数组”属性。这意味着 KVO 通知仅在设置数组对象时发送,而不是在向其中添加对象时发送。听起来您正在使用 NSMutableArray 并向其中添加对象,这解释了为什么数组控制器没有收到更改通知,因为底层对象没有更改。

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

[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 被设计为与它一起使用。您还可以免费获得一大堆东西,例如持久性、撤消支持、对象关系,以及无需编写代码即可添加对象的能力,只需直接从 UI 控件调用数组控制器上的 add:

Your array controller is observing your App Delegate's "array" property. That means KVO notifications are sent only when the array object is set, not when objects are added to it. It sounds like you are using an NSMutableArray and adding objects to it, which explains why the Array Controller is not being notified of changes, because the underlying object is not changing.

The easy solution is to wrap your calls in a will/did change block like so:

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

This manually notifies observers that there has been a change to the "array" property.

Long answer: You're doing it wrong. The whole point of having an array controller is to shift the work of managing the array to the controller class itself, so it manages the underlying array, sends out the right notifications, maintains state, etc. without you having to sweat the implementation details. A better solution would be to unhook the content array binding and just add objects to the array controller directly like so:

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

This works because the array controller manages its own array internally.

The best solution is to use Core Data. NSArrayController is designed to be used with it. You also get a whole bunch of things for free, like persistentce, undo support, object relationsips, and the ability to add objects without writing code just by calling add: on the array controller directly from your UI controls.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文