views:

69

answers:

2

I have a navigation controller, the rootviewcontroller is a tableview, which will show all file names, when user click the file, will show the file content in contentviewer. User can go back use navigation bar.

The problem is sometimes user use navigation bar go back. The app crashed. say exe-bad-access at cellForRowatIndex this line:

cell.textLabel.text = [books objectAtIndex:indexPath.row];

I spend a lot time to figure out the problem. but can not find where it is wrong. Please help

rootviewController.h

@interface rootviewController:UITableViewController{NSMutablyArray* books;}

rootviewContorller.m

import rootviewController.h;
static NSString *MyIdentifier = @"MyIdentifier";
-(void)awakefromNIb
{
    books=[[NSMutalbyArray alloc]init];
    NSString *file;
    NSString *docsDir = [NSHomeDirectory() stringByAppendingPathComponent:  @"Documents"];
    NSDirectoryEnumerator *dirEnum =
        [[NSFileManager defaultManager] enumeratorAtPath:docsDir];

    while (file = [dirEnum nextObject]) {
        if ([[file pathExtension] isEqualToString: @"doc"]) {
            [books addObject:file];
        }
    }
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
    if (cell == nil) {
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MyIdentifier] autorelease];
    }

    cell.textLabel.text = [books objectAtIndex:indexPath.row];

    return cell;
}
+1  A: 

EXEC_BAD_ACCESS means that you are accessing memory you don't own. In ObjC, it almost always it means you over-released (under-retained) something. In this case, you've almost certainly either over-released books or IndexPath. Is this a typo in your post, or do you actually have a variable called IndexPath somewhere? Your parameter is indexPath.

You should examine each of these variables and make sure they refer to allocated memory. In the debugger you can do this with po books. Or you can NSLog(@"books=%@", books).

As a note, the #1 way to avoid over-release errors is to always use accessors. Never access your ivars directly outside of an accessor (and -dealloc). Following this one rule will save you much heartache. You are breaking this rule with books, and it is likely burning you.

Rob Napier
sorry, it is a typo. I use NSLog staff. If i put on, error will happened NSLog line.I never access books objects out of this class. that is why i dont need property. thanks
angrysword
ivars should *always* be accessed through an accessor, even in their own class. If you're crashing on NSLog(@"books=%@", books), then you've over-released books somewhere. And that is almost certainly an error that an accessor would have prevented. You don't have to make the accessor public (and shouldn't unless you need to), but you should always use an accessor.
Rob Napier
A: 

When do you allocate books ?

I don't see the allocation in this code, but presumably you have it before the line [books addObject:file], since otherwise you might see the exception there.

If you do have the allocation somewhere, you might accidentally be doing something like:

books = [NSMutableArray array];

This is not the right way to do it, though, since that gives you a temporary NSMutableArray, and you want to use it for the lifetime of your object. There are multiple ways to do this; one is:

books = [[NSMutableArray alloc] init];

which gives books a retain count of 1, and books will not be deallocated until someone (hopefully you or a good friend) releases it. You probably want to add a call to [books release]; in your dealloc method to clean up that memory later.

Reference: The memory management programming guide for cocoa: mem. mgt. rules

Tyler
First line, which awakeFromNib. it actually calledbooks=[[NSMutalbyArray alloc]init];
angrysword
I agree with Rob. Sounds like you're deallocating (releasing) books somewhere else in the class. Another obscure possibility is that you could accidentally be doing something like "books = <something>" in another place, which could set books as an invalid pointer.
Tyler