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.