Disclaimer first: I'm pretty new to Objective-C and the retain model. I've been develop开发者_JAVA技巧ing in a garbage collected .NET environment for the last five years, so I've been spoiled. I'm still learning.
I'm having my iPhone app crash with EXC_BAD_ACCESS. It happens in a navigtation controller/tableview setup. When I select a row the first time, no problems. It switches in the child controller without problems. I go back and select the same row again. Program then proceeds to crash. Every other row works fine, but every second time a row is accessed, it's a crash.
I've pinpointed the location where this happens. The child controller (which is a class that I reuse for every row of the same type) that's being switched into has an array of NSString's representing the rows that will be displayed. I set it before pushing the child viewcontroller. It's there where this apparently happens.
I'm having a hard time debugging this problem, still wrestling with xcode and all. I fear there may be some vital information missing here, but maybe there is something you recognize.
Enable NSZombies.
http://www.cocoadev.com/index.pl?NSZombieEnabled
That will help you identify the object that is being over-released (probably what is going on).
So... [UINavigationController pushViewController] does not retain, does it? ;) What I did was init/alloc the controller that was going to be pushed on the navigation stack, push it and then release it. I thought the navigation controller would retain the controller. Apparently, it did not. It obviously worked the first time it was pushed, but not the second. I guess that's where the memory really got freed. Enabling zombies revealed that it was getting messages (from setters) to a deallocated object.
Why did I think pushViewController would retain the controller? I don't know; I think I got confused thinking that if you alloc it, you are also responsible for deallocing it. I somehow thought that after pushing it, it would be the navigation controller's responsibility. Seems I was wrong.
I'm still learning to get a feel for this (evil C# and garbage collection has fried my mind!). Anyone have anything to add?
To illustrate, this seems to have been wrong:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
if (selectionController == nil)
{
selectionController =
[[ConfigSelectionViewController alloc] initWithStyle:UITableViewStyleGrouped];
}
NSString *title = [self titleForSection:section row:row];
NSString *key = [self keyForSection:section row:row];
selectionController.configKey = key;
selectionController.title = title;
NSArray *listItems = [self itemsForSection:section row:row];
selectionController.list = listItems;
[self.navigationController pushViewController:selectionController animated:YES];
// DON'T DO THIS!
[selectionController release];
}
精彩评论