Pregunta

When testing I have found that outlineView:objectValueForTableColumn:byItem: is being called one extra time after the last visible row is populated resulting in a EXC_BAD_ACCESS error.

So if my display is showing 10 rows, after row 9 is populated objectValueForTableColumn is called again (without outlineView:child:ofItem: and outlineView:isItemExpandable: being called). The extra call always happens after the last visible row is populated.

Here is my code for the outlineView. There are 2 columns and 114 records in my test data set.

// (1)
- (NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {
    if (!item) {
        NSInteger parentCount = [[Parent countParents:self.dataSetID usingManagedObjectContext:self.context] integerValue];
        return parentCount;
    }
    Parent *thisParent = item;
    NSInteger childCount = [[thisParent.child allObjects] count];
    return childCount;
}

// (2)
- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    NSArray *parentArray = [Parent parentData:self.dataSetID usingManagedObjectContext:self.context];
    Parent *thisParent = [parentArray objectAtIndex:index];
    if (!item) {
        return thisParent;
    }
    NSArray *children = [NSArray arrayWithObject:[thisParent.child allObjects]];
    Child *thisChild = [children objectAtIndex:index];
    return thisChild;
}

// (3)
- (BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {
    if ([item isKindOfClass:[Parent class]]) {
        Parent *thisParent = item;
        if ([[thisParent.child allObjects] count] > 0) {
            return YES;
        }
    }
    return NO;
}

// (4)
- (id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {
    if (!item) {
        return nil;
    }
    if ([tableColumn.identifier isEqualToString:@"column1"]) {
        if ([item isKindOfClass:[Parent class]]) {
            Parent *thisParent = item;
            return thisParent.name;
        }
        Child *thisChild = item;
        return thisChild.name;
    }
    // This is column2
    if ([item isKindOfClass:[Parent class]]) {
        Parent *thisParent = item;
        return thisParent.age;
    }
    Child *thisChild = item;
    return thisChild.age;
}

I've noticed that the methods are called in the order: 1,2,3,4,4,2,3,4,4... to populate the two column NSOutlineView. For the last visible row the order is: 2,3,4,4,4 with the last call to method #4 (outlineView:objectValueForTableColumn:byItem:) causing the exception.

I can not tell you the values being passed to the method because it breaks on the call. Even if the first thing in the method is a log statement it doesn't get executed.

So I'm stumped. Any ideas why this is breaking? Did I goof on the implementation?

¿Fue útil?

Solución

In - (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item you do not appear to use item - you should be returning the child item at the specified index of a given item.

Incidentally your code is inefficient - you should be trying to make these run as fast as possible. You probably want:-

- (id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {
    if (item == nil)
        return [[Parent parentData:self.dataSetID usingManagedObjectContext:self.context] objectAtIndex:index];
    return [[NSArray arrayWithObject:[item.child allObjects]] objectAtIndex:index];
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top