pietrop.com Rotating Header Image

Manage NSCollectionView and NSArrayController selection using observers

I was using NSCollectionView and NSArrayController and I need to catch the user selection of an item of the collection.

In the official documentation there isn’t a delegate method that gets called when the user selects an item from the collection view, so you must think about another way to trigger that event.

In my case, I thought about the selectionIndexes array or the selectedObjects / selectedObject of the array controller. It was a nice idea, but it didn’t work for me, because the bindings didn’t update in real time, and this happened when I tried to select an item with the mouse click button, but it didn’t happen if I used the arrow keys on the keyboard.

So the solution comes with observers (and Google :P ). You must attach an observer to the selectionIndexes array of the NSArrayController that you want to trigger.

In the collection view controller you’ll write:

//Observer for the collection view array controller selection: "selectionIndexes"
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if([keyPath isEqualTo:@"selectionIndexes"])
    {
        //True if in the array controller of the collection view really exists at least a selected object
        if([[myArrayController selectedObjects] count] > 0)
        {
            NSLog(@"Selected objects: %@", [myArrayController selectedObjects]);
        }
        else
        {
            NSLog(@"Observer called but no objects where selected.");
        }
    }
}
 
-(void)awakeFromNib
{
    //Add a new observer to the array controller of the collection view
    [myArrayController addObserver:self forKeyPath:@"selectionIndexes" options:NSKeyValueObservingOptionNew context:nil];
}
 
- (void)dealloc
{
    //Remove the collection view array controller selectionIndexes observer
    [myArrayController removeObserver:self forKeyPath:@"selectionIndexes"];
    [super dealloc];
}

myArrayController is an instance of the NSArrayController defined in Interface Builder from which the collection view content array is binded to.

Leave a Reply