NSArrayController:如何以编程方式清除选择?

4
非常简单的问题却让我疯狂:编程清除NSArrayController选择的正确方法是什么?
我正在设计以下组件的视图:
- NSArrayController * controller1:绑定到对象数组 - NSPopUpView view1:内容绑定到controller1.arrangedObjects;值绑定到controller1.selection;“插入空占位符”已选中 - NSArrayController * controller2:绑定到存储在controller1.selection中的数组 - NSPopUpView view2:内容绑定到controller2.arrangedObjects;值绑定到controller2.selection;“插入空占位符”已选中
初始情况下,view1的内容已填充;controller1和controller2具有空选择值;view1和view2显示空占位符。选择controller1会导致controller1的选择改变并且view2的内容填充。一切正常。
我想要实现一个“清除”按钮,用于清除controller1的选择,由于绑定,这也应该清除controller2的选择并将view1和view2重置为null占位符。但是我无法找到这个非常简单功能的适当代码。更改controller1的选择无法更新在view1中显示的值。更糟糕的是,以编程方式更改控制器1的选择会导致控制器2中发生奇怪的事情:在view2中进一步选择值将无法对view1产生任何影响。
我尝试过以下方法:
- 使用[new NSArray]调用controller1的SetSelectedObjects方法。 - 使用null调用controller1的SetSelectedObjects方法。 - 对controller1使用NSNotFound调用SetSelectedIndex方法。 - 对controller1使用controller1的SelectedIndex属性调用RemoveSelectedIndex方法。 - 查看Cocoa NSArrayController文档中是否有任何清除选择值的类方法或建议。什么都没有 - 甚至没有提到这是可取的,更不用说如何实现了。
有什么想法吗?谢谢...
4个回答

4
根据苹果开发者文档,可以使用setSelectionIndexes:来完成此操作:

要取消选择所有索引,请传递一个空的索引集。

Objective-C: [arrayController setSelectionIndexes:[NSIndexSet indexSet]]; Swift: arrayController.setSelectionIndexes( NSIndexSet() )

2

尝试使用 controller1.selectionIndex = NSIntegerMax; 看看是否可行。我进行了一个简单的测试,将一个标签绑定到数组控制器的选择,当我将 selectionIndex 设置为 NSIntegerMax 时,标签中显示了“无选择”占位符。


这是苹果设定的方式,所以我认为它并不丑陋——如果在表格没有选择时记录selectionIndex,那就是你得到的结果(实际上只会打印出一个非常大的数字,但我认为那就是NSIntegerMax)。 - rdelmar

1
事实证明,NSArrayController页面确实包含了一个清除选择的建议:
setSelectionIndexes: 设置接收器的选择索引并返回一个布尔值,指示选择是否更改。 (BOOL) setSelectionIndexes: (NSIndexSet *) indexes 讨论 尝试更改选择可能会导致提交失败的commitEditing消息,从而拒绝选择更改。 要选择接收器的所有对象,索引应该是一个具有索引[0...count-1]的索引集。要取消选择所有索引,请传递一个空的索引集。
然而,我实际上已经尝试过这个方法,但仍然存在问题。
总的来说:
创建两个类,A和B,其中A包含一个属性“NSArray *b_list”,该属性包含B实例的列表。
创建一个应用程序,具有属性“NSArray *a_list”。使用一些A实例填充它,并使用一些B实例填充每个A实例的b_list。
创建一个带有两个数组控制器的窗口,Controller_A(绑定到a_list)和Controller_B(绑定到Controller_A.selection.b_list)。
在窗口中创建两个弹出式按钮,Popup_A(绑定到Controller_A.arrangedObjects)和Popup_B(绑定到Controller_B.arrangedObjects)。
创建一个“清除”按钮,其中包含一些逻辑以清除Controller_A的选择。(“某些逻辑”是Apple文档推荐的方法或任何其他方法。)
运行应用程序。选择Popup_A中的条目。注意,Popup_B将与Controller_A.selection.b_list的实例一起填充,正如它应该做的那样。
现在点击“清除”按钮。

错误:请注意,虽然 Popup_A 的内容和选择正确变为空,但是在 Popup_B 中并没有发生同样的情况:它呈现了一个空白条目和一个已选中(空白)的项目。请注意,Controller_B 的选择属性表明存在选择,但其属性很奇怪:selectedIndex 指向 0 而不是 NSNotFound,并且 selectedIndexes 包括非空选择整数范围。

这显然是绑定逻辑的错误,可能会导致一些异常和逻辑错误。例如,如果 B_controller.selection 附加了任何类型的绑定,则清除 A_controller 将引发与 B_controller 中的选择值相关的异常,因为它指示存在选择但指向垃圾。

我的解决方法是不直接将任何东西绑定到 B_controller 的选择上。相反,以编程方式访问 B_controller,并考虑 A_controller 的选择值,如下所示:

// setting some property c to the value of b_controller:
if ((B_controller.selectedIndex == NSNotFound) || A_controller.selectedIndex == NSNotFound))
    c = nil;
else
    c = [B_controller objectAtIndex: [B_controller.selectedIndex]];

我也将这些信息提交给苹果的错误报告。


在控制器 B 上,您是使用“Content Array”绑定还是“Content”绑定? - paulmelnikow

1

回答一个很久以前的问题,但仍然有用。

我也需要同样的东西,对我来说这个方法有效:

[arrayController setAvoidsEmptySelection:NO];
NSIndexSet *indexes = [NSIndexSet indexSetWithIndexesInRange:
    NSMakeRange(NSNotFound, 0)];
[arrayController setSelectionIndexes:indexes];

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接