Search code examples
iphonememoryuiviewcontrolleruinavigationcontrollerdealloc

UINavigationController and UIViewController dealloc


I recently changed my app to use a UINavigationController, I was using a UINavigationBar before, with cascade subView adding, which was a bit tenuous.

I'm facing a problem of memory usage. Leaks tool doesn't show any leak, but ViewControllers I create and add to the UINavigationController never seem to be released. So memory usage grows everytime I create a new VC and then press the NavigationController's back button.

I simply create and add my VCs this way:

DetailViewController* detailViewController = [[DetailViewController alloc] initWithNibName:@"DetailViewController" bundle:nil];
// setups
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];

The app never goes through ViewController's dealloc and viewDidUnload methods. Shouldn't these be called everytime I press the back button?

I've searched many tutorials and read Apple's memory management, but there's nothing about VC's lifetime in memory when using NavigationController.


Solution

  • Maybe you are not doing something wrong and instead you are facing something like this

    In the Blog post it was the question whether we have to manually release IBOutlets or not. As it turns out we should. This was reproduceable in iOS 3.1.3 but I didn't test it in iOS 4.0 yet.

    The second aproach is to override your view controllers retain and release method and print out the retain count. I had a simimlar problem, that some view controllers dealloc method did not called so I override this methods to see wether someone has still a retain on it. As it turns out it did.

    Edit:
    When I printed my retain count, it would sometimes reach ~98 caused from the framework, so thats not really to worry.

    If your last retain count stays at 2 and the dealloc method won't be called, than there is someone that has still a retain on it.

    In this case you should search on other places.

    For example another problem I encountered during this same problem: Sometimes I would use

    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateUI) userInfo:nil repeats:YES]

    to constantly update the UI. But what I forgot was, that the NSTimer will retain the target object (which was the ViewController). Because the NSTimer retained your view controller your dealloc will never be called because someone (NSTimer) has still a retain on it. So you have to make sure to invalidate the NSTimer BEFORE dealloc method to properly release the view controller.

    Edit2 in response for a comment below:
    A retain declaired property does as follows (exsample):

    - (void)setTarget:(id)value {
      if (value != target) { 
        [target release];
        target = [value retain];
    }
    

    So it does first release your current self.target then retains the new value. Since you are assigning nil your target will be nil afterwards. Further info about Properties can be found in the Apple doc.