NSArrayController: how to programmatically clear a selection?

A very simple question that drives me crazy: what is the right way to programmatically clear NSArrayController selection?

I am developing a view with the following components:

  • NSArrayController * controller1: bound to an array of objects
  • NSPopUpView view1: content bound to .arrangedObjects controller; The value associated with the controller. Choice; Zero Label Inserts selected
  • NSArrayController * controller2: bound to an array stored in controller1.selection
  • NSPopupView view2: content bound to .arrangedObjects controller; value associated with the controller. Zero Label Inserts selected

Initially, the contents of view1 are populated; controller1 and controller2 have zero selection values; and view1 and view2 display null placeholders. Selecting controller1 invokes selection of controller1 and populating the contents of view2. Things are good.

I would like to implement the Clear button, which clears the selection of controller1, which, thanks to the bindings, should also clear the selection of controller2 and reset view1 and view2 to zero placeholder. For life of me, I cannot find the correct code for this very simple function. Changing the selection of controller1 does not allow updating the value shown in view1. Worse, changing the choice of controller1 programmatically leads to 2 strange things in the controller: further selection of values ​​in view1 has no effect on view2.

Things I tried:

  • Call the SetSelectedObjects method of controller1 with [NSArray new].

  • Call the SetSelectedObjects method of controller1 with a null value.

  • Call the SetSelectedIndex method of controller1 using NSNotFound.

  • Call the RemoveSelectedIndex method of controller1 with the SelectedIndex property of controller 1.

  • Looking at the Cocoa NSArrayController documentation for any method or class clause to clear the selection value. Nothing - not even mentioning it is desirable, not to mention how to do it.

Any ideas? Thanks...

+4
source share
4 answers

Try control1.selectionIndex = NSIntegerMax; and see if it works. I did a simple test with a label related to the choice of an array controller, and when I set selectionIndex to NSIntegerMax, the selection location was not highlighted in the shortcut.

+2
source

According to the Apple Developer Documentation, this can be done using setSelectionIndexes:

To deselect all indexes, pass an empty set of indexes.

Objective-C:

[arrayController setSelectionIndexes:[NSIndexSet indexSet]];

Swift:

arrayController.setSelectionIndexes( NSIndexSet() )

+2
source

Answer a very old question, but still.

I just needed the same thing, and it worked for me:

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

As it turned out, the NSArrayController page has the only recommendation for cleaning the selection:

setSelectionIndexes:

Sets the receiver selection indices and returns a boolean that indicates whether the selection has changed.

(BOOL) setSelectionIndexes: (NSIndexSet *) indexes

Discussion

Attempting to change the selection may cause the commitEditing message to fail, which negates the selection change.

To select all recipient objects, the indices must be an index with indices [0 ... count -1]. To deselect all indexes, pass an empty set of indexes.

However, I really tried this, and it still left me with a problem.

Generalization:

  • Create two classes: A and B, where A contains the NSArray * b_list property, which contains a list of instances of B.

  • Create an application with the property "NSArray * a_list". Fill it with some instances of A and fill in the b_list of each instance of instance B with instances.

  • Create a window with two array controllers, Controller_A (attached to a_list) and Controller_B (attached to Controller_A.selection.b_list).

  • Create two pop-up buttons in the window, Popup_A (bound to Controller_A.arrangedObjects) and Popup_B (bound to Controller_B.arrangedObjects).

  • Create a “Clear” button with some logic to clear the Controller_A selection. (“Some logic” is either the method recommended in the Apple documentation, or any other method.)

  • Launch the app. Select an entry in Popup_A. Note that Popup_B is populated with Controller_A.selection.b_list instances, as it should be.

  • Now click the "Clear" button.

ERROR. Note that as long as the contents and selection of Popup_A correctly become null, this does not happen in Popup_B: it represents an empty record with one selected (empty) element. Also note that the selection properties of Controller_B indicate that there is a selection, but its properties are strange: selectedIndex points to 0 instead of NSNotFound, and selectedIndexes includes a non-empty range of select integers.

This is clearly a bug with binding logic, which can definitely cause some exceptions and logical errors. For example, if any binding is bound to B_controller.selection, clearing A_controller will throw an exception related to the selection value in B_controller, since it indicates a selection but indicates garbage.

My workaround is not to bind anything directly to the B_controller selection. Instead, programmatically access the B_controller and given the value of the A_controller selection, for example:

 // 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]]; 

I also submit an error report in Apple with this information.

0
source

All Articles