将NSArrayController绑定到NSPopupButton和NSTextField

eri*_*icg 19 macos cocoa nsarraycontroller cocoa-bindings

我想要完成的事情似乎应该相当简单.我在这里放了一个示例项目.

我有一个NSArrayController充满了NSDictionaries数组.

[[self controller] addObject:@{ @"name" : @"itemA", @"part" : @"partA" }];
[[self controller] addObject:@{ @"name" : @"itemB", @"part" : @"partB" }];
[[self controller] addObject:@{ @"name" : @"itemC", @"part" : @"partC" }];
Run Code Online (Sandbox Code Playgroud)

我正在使用'name'键来填充NSPopupButton以及此数组中的项目.使用以下绑定可以轻松完成此操作

绑定

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

textfieldbindings

仅使用这些绑定,文本字段就会显示"partC".

初始显示

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

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

选定的对象

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

窗口2

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

ipm*_*mcc 55

在这种情况下,请勿使用"选定对象".将弹出窗口的"Selected Index"绑定绑定到NSArrayController的selectionIndexController Key.在你的示例项目上试了一下它就可以了.

编辑:

你问为什么适合使用selectionIndexselectedObject.首先是一些背景:

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

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

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

通过对该selection属性的理解,让我们退一步看看为什么在这种情况下使用它不正确. NSPopUpButton试图变得聪明:你已经通过内容内容值绑定为它提供了一个应该在菜单中的列表.然后你还告诉它你要将它的Selected Object绑定到NSArrayControllerselection属性.您可能认为这是一种"只写"绑定 - 即"亲爱的弹出窗口,请将用户选择并将其推入arrayController",但绑定实际上是双向的.因此,当绑定刷新时,弹出窗口首先使用Content/Content Values绑定中的所有项填充菜单,然后它会说:"哦,你说值arrayController.selection是我的选定对象.这很奇怪 - 它不在与我的内容/内容值绑定绑定的事物列表.我最好将它添加到列表中!我会通过调用-description它来执行此操作,并将该字符串插入菜单中." 但是你从Selected Object绑定得到的对象是上面描述的不透明选择对象(你可以从结果中看出它是类_NSControllerObjectProxy,一个私有到AppKit类,由前导下划线暗示).

总而言之,这就是为什么将弹出窗口的Selected Object绑定绑定到数组控制器的selection控制器键是错误的.不幸的是,但是我确信你已经发现,Cocoa绑定的文档只是开始划伤表面,所以不要感觉不好.我几乎每天都在使用Cocoa绑定,在一个大型项目中,已经好几年了,我仍然觉得有很多用例我还没有完全理解.

  • @ericgorr试图解释一些; 希望它有意义.这是一个复杂的话题. (2认同)