Chris
Chris

Reputation: 1037

NSOutlineTableView Crash after last element

I have an NSOutlineTableView that is displaying hierarchical HTML data, loaded from an HTML parser (each HTML tag is an object with attributes and an array of it's children). For some reason, this code crashes AFTER it has run through all the objects. That is to say, I see NSLog() results for all objects in the HTML, but after that the code crashes:

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

    if (item==nil) {
        item=rootNode;
    }
    NSLog(@"looking for child %d of element %@",index, item);
    return [[item children] objectAtIndex:index];

}


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

    if (item==nil) {
        item=rootNode;
    }
    NSLog(@"Element %@ has %i children", item, [[item children] count]);
    return [[item children ]count];

}


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

    NSLog(@"is item %@ with %@ children expandable?",item,[item children]);
    return [[item children] count]>0;

}


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

    if (![item isKindOfClass:[HTMLNode class]]) {   //////CRASH ON THIS LINE (or at least in this function)
        return @"";
    }

    NSLog(@"Object value for: %@",item);

    return [NSString stringWithFormat:@"%@",[item description]];

}

Here is an example run: HTML content: @"<ul></ul><span class='spantext1'></span><span class='spantext2'></span>";

Output:

Element <HTMLNode: 0x7fb9234462a0> body has 3 children

looking for child 0 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb923437d40> ul with (
) children expandable?

Object value for: <HTMLNode: 0x7fb923437d40> ul

looking for child 1 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb9249255c0> span with (
) children expandable?

Object value for: <HTMLNode: 0x7fb9249255c0> span

looking for child 2 of element <HTMLNode: 0x7fb9234462a0> body

is item <HTMLNode: 0x7fb92491e1d0> span with (
) children expandable?

Object value for: <HTMLNode: 0x7fb92491e1d0> span
(lldb) (crash with EXC_BAD_ACCESS)

Here is the top of the call stack:

objc_msgSend() selector name: isKindOfClass:
objc[23702]: garbage collection is OFF

Thread 0 Crashed:: Dispatch queue: com.apple.main-thread
0   libobjc.A.dylib                 0x00007fff846e7110 objc_msgSend_vtable4 + 16
1   com.303DesignLabs.SiteStats     0x0000000109dd44fd -[HTMLTreeOutlineController outlineView:objectValueForTableColumn:byItem:] + 189 (HTMLTreeOutlineController.m:51)

It almost appears as if it's trying to run objectValueForTableColumn once more, after all the data has been run thru. Like I said, the crash occurs after the entire object hierarchy has been run thru (as evidenced by terminal output). At any rate, before the crash the tableView appears on the screen for a split second, with all three elements in their respective rows.

Upvotes: 0

Views: 177

Answers (1)

Michael Dautermann
Michael Dautermann

Reputation: 89509

"EXC_BAD_ACCESS" usually means you're trying access a nil object or pointer.

And from what I can see in your code up there, it looks like you're always assuming "[item children]" is not nil.

What happens if "[item children]" has no children? is the result NULL? Should you be calling objectAtIndex or count on a NULL object? My guess is NO.

You should probably return something sensible for each function if there are no children for any given item.

Upvotes: 1

Related Questions