Pregunta

I am experiencing a bad access error when an item of my NSOutlineView is expanded. When NSStrings are allocated with stringWithFormat:, there is an EXC_BAD_ACCESS error when expanding the outline. When they are replaced with strings in the form of @"string", there is no error.

I assume something is releasing with ARC, but I don't know how to keep it from happening. What doesn't look right here?

-(NSInteger)outlineView:(NSOutlineView *)outlineView numberOfChildrenOfItem:(id)item {

    if(!item)
        return [_characterList count];
    else if( [item isKindOfClass:[Character class]] )
        return 3;

    return 0;

}

-(BOOL)outlineView:(NSOutlineView *)outlineView isItemExpandable:(id)item {

    if( [item isKindOfClass:[Character class]] )
        return YES;

    return NO;

}

-(id)outlineView:(NSOutlineView *)outlineView child:(NSInteger)index ofItem:(id)item {

    if (!item)
        return (Character*)[_characterList objectAtIndex:index];
    else {

        NSLog(@"%@", item);

        Character *characterItem = (Character*)item;

        switch (index) {
            case 0:
                return [NSString stringWithFormat:@"Api key: %@", [characterItem apiKey]];
                break;
            case 1:
                return [NSString stringWithFormat:@"Access Mask: %@", [characterItem mask]];
                break;
            case 2:
                return @"Last Updated: today";
                break;
            default:
                break;
        }

    }

    return nil;

}

-(id)outlineView:(NSOutlineView *)outlineView objectValueForTableColumn:(NSTableColumn *)tableColumn byItem:(id)item {

    if([item isKindOfClass:[Character class]])
        return [(Character*)item name];
    else
        return item;

    return nil;

}
¿Fue útil?

Solución

The solution I have come up with (but don't particularly like). Replace outlineView:objectValueForTableColumn:byItem: with the following code.

-(NSView*)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item {

NSTableCellView *cell = [outlineView makeViewWithIdentifier:@"characterColumn" owner:self];

    if([item isKindOfClass:[Character class]]) {
        [cell.textField setStringValue:[item name]];
    } else if([item isKindOfClass:[NSString class]]) {
        [cell.textField setStringValue:item];
    }

    return cell;

}

Basically what this does is exactly what I'd expect the cell code to do, but it appears to retain things properly. Any insight from the masses?

EDIT: Here's the deal. NSOutlineView's dataSource delegate methods are a little bit more particular about ownership. It's not something that you have to deal with usually with a vanilla NSTableView, since there are not multiple levels of item. Basically, you need to create all of the objects for display elsewhere and make sure they are managed in memory elsewhere, because NSOutlineViewDataSource isn't going to do any of that for you.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top