macos - 将 NSArrayController 绑定(bind)到 NSPopupButton 和 NSTextField

标签 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" }];

我正在根据“名称”键使用此数组中的项目填充 NSPopupButton。这可以通过以下绑定(bind)轻松完成

bindings

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

textfieldbindings

单独使用这些绑定(bind),文本字段会显示“partC”。

initial display

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

我认为这只是在 NSPopupButton 上设置“选定对象”绑定(bind)的问题

selected object

但这不起作用。由于某种奇怪的原因,我最终在我的菜单中使用了代理对象(提供了为什么是奖励的原因)。

window2

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

最佳答案

在这种情况下不要使用“选定对象”。将弹出窗口的“Selected Index”绑定(bind)到 NSArrayController 的 selectionIndex Controller 键。在您的示例项目中试用了它并且它有效。

编辑:

你问为什么使用 selectionIndex 合适在 selectedObject .首先介绍一下背景:

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

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

  • selectionIndexes如上所述 - 一个 NSIndexSet包含 中所选项目的索引内容 阵列
  • selectionIndex对于不支持多选的应用程序来说,这是一个方便的选项。可以认为它等价于 arrayController.selectionIndexes.firstIndex .
  • selectedObject在单选情况下也很有用,在概念上对应于 ContentObjectsArray[arrayController.selectionIndexes.firstIndex]
  • selection 中返回一个特殊对象(对消费者不透明),该对象代理读取和写回底层对象(或多选情况下的对象)。内容数组 阵列 Controller 。它的存在是为了在多个选择情况下一次编辑多个对象,并为其他特殊情况提供支持。 (你应该认为这个属性是只读的;因为它的类型对消费者是不透明的,你永远无法创建一个合适的新值来写入它。发出类似这样的调用是有意义的: -[arrayController.selection setValue: myObject forKey: @"modelKey"] ,但它没有意义拨打类似 -[arrayController setValue: myObject forKey: @"selection"]
  • 的电话

    有了那个了解selection属性,让我们退后一步,看看为什么在这种情况下使用它不正确。 NSPopUpButton尽量聪明:您已经通过 向它提供了菜单中应包含的内容列表。内容 内容值 绑定(bind)。然后你还告诉它你想绑定(bind)它的所选对象 NSArrayControllerselection属性(property)。您可能认为这是一个“只写”绑定(bind)——即“亲爱的弹出窗口,请接受用户的选择并将其推送到 arrayController 中”,但绑定(bind)确实是双向的。因此,当绑定(bind)刷新时,弹出窗口首先使用来自 的所有项目填充菜单。内容/内容值 绑定(bind),然后它说,“哦,你说 arrayController.selection 处的值是我的 选定对象 。这很奇怪——它不在与我的 内容/内容值绑定(bind)的事物列表中 绑定(bind)。我最好为你把它添加到列表中!我会通过在它上面调用 -description 来做到这一点,然后将该字符串插入菜单中。”但是你从中得到的对象所选对象 binding 是上面描述的不透明选择对象(您可以从结果中看到它属于 _NSControllerObjectProxy 类,这是一个私有(private)的 AppKit 类,如前导下划线所示)。

    总之,这就是为什么要绑定(bind)弹出窗口的 所选对象 绑定(bind)到阵列 Controller 的 selection Controller 键在这里是错误的。说来可悲,但我敢肯定你已经发现, cocoa 绑定(bind)的文档仅开始划伤表面,所以不心疼。几年来,我几乎每天都在使用 Cocoa 绑定(bind),在一个大型项目中,我仍然觉得有很多用例我还没有完全理解。

    关于macos - 将 NSArrayController 绑定(bind)到 NSPopupButton 和 NSTextField,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14888175/

    相关文章:

    macos - 如何实现带有下拉菜单的工具栏按钮?

    Java 程序删除 (Mac/Linux)

    cocoa - 在cocoa中点击NSRect打开一个NSWindow

    swift - Mac OS 更改绑定(bind)核心数据控件的值

    cocoa - GCD 阻止不更新 NSCollectionView

    cocoa - NSArrayController 的绑定(bind)在哪里声明的?

    macos - Bash 编程 - 创建自定义终端命令 - Mac

    python - 使用 python 和 cocoa 设置 : OS X 10. 6.6 + XCode3.2

    objective-c - 如何使用单独的sheetController显示不同NIB包含的工作表

    macos - 带旋转的图层支持 View 上的核心动画