I have an NSCollectionView
that is showing some images. I have implemented an NSCollectionViewDelegate
to tell it which items should be selected and/or highlighted. I'm using a stock NSCollectionViewItem
to draw the images and their names. When the user selects an item, my delegate gets the messages about highlight state changes:
- (void)collectionView:(NSCollectionView *)collectionView
didChangeItemsAtIndexPaths:(NSSet<NSIndexPath *> *)indexPaths
toHighlightState:(NSCollectionViewItemHighlightState)highlightState
{
[collectionView reloadItemsAtIndexPaths:indexPaths];
}
I do a similar thing for didSelect
/didDeselect
:
- (void)collectionView:(NSCollectionView *)collectionView
didSelectItemsAtIndexPaths:(nonnull NSSet<NSIndexPath *> *)indexPaths
{
[collectionView reloadItemsAtIndexPaths:indexPaths];
}
In the NSCollectionViewItem
s view
, I do the following:
- (void)drawRect:(NSRect)dirtyRect {
[super drawRect:dirtyRect];
NSColor* bgColor = [[self window] backgroundColor];
NSColor* highlightColor = [NSColor selectedControlColor];
NSRect frame = [self bounds];
NSCollectionViewItemHighlightState hlState = [collectionViewItem highlightState];
BOOL selected = [collectionViewItem isSelected];
if ((hlState == NSCollectionViewItemHighlightForSelection) || (selected))
{
[highlightColor setFill];
}
else
{
[bgColor setFill];
}
[NSBezierPath fillRect:frame];
}
The problem I'm seeing is that drawing the highlight or selection appears to be random. When it does draw the selection, it's almost always on the items the user has actually selected (though it often leaves off the last item for some reason). Occasionally, it will select a different item the user did not click on or drag over. Often, though, it just doesn't draw.
I've added printing to verify that it is calling -didChangeItemsAtIndexPaths:toHighlightState:
and -didSelectItemsAtIndexPaths:
. Is there anything I'm doing wrong here?
I've added some logging to the view's -drawRect:
method, and it doesn't appear to be getting called on all transitions, even though I'm calling -reloadItemsAtIndexPaths:
in the -didChange*
methods. Why not?
I've also noticed that the delegate's -should/didDeselectItemsAtIndexPaths:
does not seem to get called ever, even though the -should/didSelectItemsAtIndexPaths:
does get called. Why is that?