cocoacore-datanstableviewnsoutlineviewnsindexset

Crash in NSOutlineView subclass - NSRangeException


I have a subclass for NSOutlineView which listens to NSManagedObjectContext change notifications and updates the outlineView accordingly. I'm getting a strange crash at some point that my users are reporting (that I can't reproduce on my own) ... the crash itself is a straight-forward NSRangeException:

*** Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSIndexSet initWithIndexesInRange:]: Range {18446744073709551614, 1} exceeds maximum index value of NSNotFound - 1'

But the confusing part is the code where this is happening:

- (void) addedObject: (CommonListData *) item toExistingSection: (CommonListData *) existingSection atIndex: (NSInteger) index {

if (index != NSNotFound) {
    [self beginUpdates];
    [self insertItemsAtIndexes: [NSIndexSet indexSetWithIndex: index] inParent: existingSection withAnimation:NSTableViewAnimationEffectFade | NSTableViewAnimationSlideDown];
    [self endUpdates];

    NSInteger scrollPosition = [self rowForItem: item];
    if (scrollPosition != NSNotFound && scrollPosition !=0) {
        NSIndexSet *indexSet = [NSIndexSet indexSetWithIndex:scrollPosition - 1]; // crashes here

Now if I'm checking for NSNotFound, and for 0, why is indexSetWithIndex:(scrollPosition-1) still giving a NSRangeException? What else can I check for to make sure the scollPosition is valid or invalid?

Not sure if this is relevant, but it's only happening when my Core Data stack is connected to iCloud and I get a NSPersistentStoreDidImportUbiquitousContentChangesNotification, and I use the context to do a mergeChangesFromContextDidSaveNotification with the notification.


Solution

  • -[NSOutlineView rowForItem:] returns -1 (not NSNotFound) if the item isn't in the outline. So, scrollPosition is -1 and scrollPosition - 1 is -2. +[NSIndexSet indexSetWithIndex:] takes an NSUInteger which is (of course) unsigned, so -2 becomes 18446744073709551614.