问题
I have a table view that when a cell is selected it pushes a view controller onto the navigation stack:
SAPostTableViewController *postViewController = [[SAPostTableViewController alloc] initWithNibName:NSStringFromClass([SAPostTableViewController class]) bundle:nil];
postViewController.site = site;
[self.navigationController pushViewController:postViewController animated:YES];
[postViewController release];
SAPostTableViewController has a static tableView which, and it's cells, are loaded from a nib.
I have overridden the initWithNibName:bundle: method:
-(id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
if (self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]) {
self.sections = [NSMutableDictionary dictionary];
}
return self;
}
sections is a retained property.
In viewDidLoad of SAPostTableViewController I have this:
- (void)viewDidLoad
{
[super viewDidLoad];
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(cellVisibiltyChanged:) name:@"SAStaticCellVisibiltyChanged" object:nil];
}
and so to match in viewDidUnload:
- (void)viewDidUnload
{
[super viewDidUnload];
[[NSNotificationCenter defaultCenter] removeObserver:self name:@"SAStaticCellVisibiltyChanged" object:nil];
}
However when I press the back button in the navigation bar (all standard behaviour, no override) and SAPostTableViewController is popped, it doesn't call viewDidUnload or dealloc. So this means that if I then reselect the cell that pushes SAPostTableViewController it creates a new instance of SAPostTableViewController and repeating this back and forward just means the memory usage keeps increasing as the popped SAPostTableViewControllers never get deallocated. (I know this by running Instruments on allocations)
The weird thing is that if I release SAPostTableViewController twice then it works as I'd expect:
SAPostTableViewController *postViewController = [[SAPostTableViewController alloc] initWithNibName:NSStringFromClass([SAPostTableViewController class]) bundle:nil];
postViewController.site = site;
[self.navigationController pushViewController:postViewController animated:YES];
[postViewController release];
[postViewController release];
(If I add a third release statement, it crashes as I'd expect it to with just 2)
I have resorted to using retainCount and stepped through the lines of code the are executed in the first line of the directly above code, the retainCount remains at 1. It jumps up between the first and second line, so I can't see anywhere it is being retain an extra time?
The SAPostTableViewController is only used in this place, it is not a delegate of anything, nor does it have a delegate.
How can I find a fix, or is it something simple I've missed?
Here is what Instruments shows after pushing SAPostTableViewController just once (with only one release statement):
And what it shows after navigating back and forth repeatedly (again, one release statement):
回答1:
You are creating a new Object when you clic one Cell, why you don't create your Object (SAPostTableViewController) in the init Method and then Push the same object watch time you click in Cell
you can do something like this :
postViewController = [[SAPostTableViewController alloc] initWithNibName:NSStringFromClass([SAPostTableViewController class]) bundle:nil];
and in the
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
postViewController.site = site;
[self.navigationController pushViewController:postViewController animated:YES]; [postViewController release];
}
回答2:
I don't know what your problem is, but here are some things to consider:
You should absolutely NOT release the view controller twice. If you have indeed discovered a memory leak in UIKit (which is unlikely), then it is likely it would be fixed in a future version of UIKit. That means that anyone running an old version of your app on a new version of the operating system would experience nothing but crashes (due to over-releasing the view controller). It is better to leak than to crash. A leaky app is still a usable app (at least until you leak too much). But a crashing app can't be run at all.
-viewDidUnloadis not doing what you think it should be doing. It is only called when the view controller's view is unloaded due to memory pressure. It is not called during normal deallocation. It would be wiser to rely on-viewWillAppear:and-viewDidDisappear:instead.
来源:https://stackoverflow.com/questions/10664710/uiviewcontroller-not-being-released-when-popped