将NSArrayController绑定到NSPopupButton&的NSTextField

时间:2013-02-15 04:21:39

标签: macos cocoa cocoa-bindings nsarraycontroller

我想要完成的事情似乎应该相当简单。我已经放置了一个示例项目here

我有一个NSArrayController,里面装满了NSDictionaries数组。

[[self controller] addObject:@{ @"name" : @"itemA", @"part" : @"partA" }];
[[self controller] addObject:@{ @"name" : @"itemB", @"part" : @"partB" }];
[[self controller] addObject:@{ @"name" : @"itemC", @"part" : @"partC" }];

我使用'name'键填充NSPopupButton,其中包含此数组中的项目。使用以下绑定可以轻松完成此操作

bindings

然后,我想根据NSPopupButton的当前选择,使用'part'键中的文本填充NSTextField。我已经设置了以下绑定:

textfieldbindings

仅使用这些绑定,文本字段就会显示“partC”。

initial display

但是,如果我更改NSPopupMenu的值,则文本字段显示的内容不会更改。

我认为这只是在NSPopupButton上设置'Selected Object'绑定的问题

selected object

但这不起作用。我最终得到了菜单中的代理对象,原因有些奇怪(提供原因可能是奖金)。

window2

那么,我需要做些什么才能使这项工作?

1 个答案:

答案 0 :(得分:53)

在这种情况下,请勿使用“选定对象”。将弹出窗口的“选定索引”绑定绑定到NSArrayController的selectionIndex控制器密钥。在你的示例项目上试了一下它就可以了。

编辑:

您问为什么使用selectionIndex而不是selectedObject是合适的。首先是一些背景:

绑定弹出菜单时,您可以绑定三个虚拟“集合”:内容是抽象的“应该在菜单中的事物列表” - 您必须始终指定内容。如果您既未指定内容对象,也未指定内容值,则绑定到内容的值集合将用作“对象”,由-description方法返回的字符串将用作“值”。换句话说,内容值是弹出窗口中显示的字符串,内容对象是它们对应的内容(可能不是字符串,可能是没有适合在弹出窗口中生成文本的-description方法。这里要认识到的重要一点是,这里可能存在三种不同的“虚拟阵列”:内容的数组,内容对象的数组(可能不同)以及内容值的数组(也可能不同)。它们都具有相同数量的值,通常,内容对象内容值将是内容阵列。

接下来要认识到的是,NSArrayController生活中的一部分目的是跟踪用户的选择。在弹出窗口的情况下,这只是温和的(如果有的话)有趣,但在NSTableView的情况下开始变得更有趣。在内部,NSArrayController通过在{strong>内容数组中保留包含在任何给定时间选择的索引的NSIndexSet来跟踪此情况。从那里开始,为了您的方便,选择状态以几种不同的方式暴露出来:

  • selectionIndexes如上所述 - NSIndexSet包含内容数组中所选项目的索引
  • 对于不支持多选的应用程序,
  • selectionIndex是一个方便的选项。可以认为它等同于arrayController.selectionIndexes.firstIndex
  • selectedObject在单一选择案例中也很有用,并且在概念上与ContentObjectsArray[arrayController.selectionIndexes.firstIndex]
  • 相对应
  • selection返回一个特殊对象(对于使用者不透明),代理在内容数组中读取并写回基础对象(或多个选择中的对象)阵列控制器。它的存在是为了在多个选择案例中一次编辑多个对象,并为其他特殊情况提供支持。 (您应该将此属性视为只读;因为它的类型对于使用者来说是不透明的,所以您永远无法创建一个合适的新值来写入它。调用类似于-[arrayController.selection setValue: myObject forKey: @"modelKey"]的调用是有意义的,但它是< em> not 有意义地拨打-[arrayController setValue: myObject forKey: @"selection"]
  • 等电话

通过对selection属性的理解,让我们退后一步,看看为什么在这种情况下使用它不正确。 NSPopUpButton试图变得聪明:您已通过内容内容值绑定为其提供了菜单中应包含的内容列表。然后你还告诉它你要将选定对象绑定到NSArrayController的{​​{1}}属性。您可能认为这是一种“只写”绑定 - 即“亲爱的弹出窗口,请将用户选择并将其推入arrayController”,但绑定实际上是双向的。因此,当绑定刷新时,弹出窗口会首先使用内容/内容值绑定中的所有项目填充菜单,然后它会说:“哦,你说selection处的值是我的选定对象。这很奇怪 - 它不在我的内容/内容值绑定的绑定列表中。我最好将它添加到列表中!我会通过在其上调用arrayController.selection并将该字符串插入菜单中来做到这一点。“但是从选定对象绑定中获得的对象是上面描述的不透明选择对象(您可以从结果中看出它是类-description,私有到AppKit类正如领先的下划线暗示的那样。)

总而言之,那是为什么将弹出窗口的选定对象绑定绑定到数组控制器的_NSControllerObjectProxy控制器密钥这是错误的做法。说来可悲,但我敢肯定你已经发现,可可绑定的文档仅开始划伤表面,所以不心疼。我几乎每天都在使用Cocoa绑定,在一个大型项目中工作了好几年了,我仍然觉得有很多用例我还没有完全理解。