JAHelia
JAHelia

Reputation: 7902

releasing UIViewController subclasses does not actually free up memory

I have a UINavigationController object (named LoginNav) which consists of ViewController1 & ViewController2, my iPad app starts by loading a UISplitViewController subclass (named mainSplitViewController) and then presenting LoginNav modally on top of it (this is by the way done in didFinishLaunchingWithOptions method of AppDelegate like this:

[self.mainSplitViewController presentModalViewController:LoginNav animated:YES];).

Once ViewController1 is shown, I tap a UIButton in it to push ViewController2, when I finish working in ViewController2 I tap a UIButton in it to call [self.navigationController dismissModalViewControllerAnimated:YES]; to dismiss LoginNav with both of its view controllers and show mainSplitViewController's contents.

There is a dealloc method in both ViewController1 & ViewController2 with NSLog statement in each one, once loginNav is dismissed, the NSLogs never get fired, but doing [self.navigationController.viewControllers objectAtIndex:0] release]; & [self.navigationController.viewControllers objectAtIndex:1] release]; right after [self.navigationController dismissModalViewControllerAnimated:YES]; fires both NSLogs.

I commented out the above two release statements, then I launched the Allocations instrument, and launched the app again and pushed ViewController2 then dismissed loginNav as described above, and looked at Live Bytes column (All Allocations value ) it was 6.9 MB right after the dismissal of loginNav, then I did this step again but in this case using the two release statements, I got exactly a 6.9 MB value on Live Bytes column.

Two Questions:

1) why do not the dealloc methods of ViewController1 & ViewController2 never get fired after the dismissal of the navigation controller LoginNav that holds them ? and is it correct to do the above two release statements to release these view controllers ?

2) why releasing ViewController1 & ViewController2 does not free up memory ?

p.s. there is no single variable (or IBOutlet) being held in memory in both ViewController1 & ViewController2, everything is released in both of them.

Upvotes: 0

Views: 615

Answers (3)

ader
ader

Reputation: 5393

Another thing you might have fallen foul of is a retained property (such as a delegate) in your LoginNav.

Upvotes: 0

sc0rp10n
sc0rp10n

Reputation: 1118

These kinds of issues are nearly impossible to troubleshoot without seeing all your code. When you manage memory manually, there are multiple areas that you can go wrong. For example the following code will leak:

- (void)didSelectSomethingInViewControllerOne
{
    ViewController2 *vc2 = [[ViewController2 alloc] init];
    [self.navigationController pushViewController:vc2 animated:YES];
}

In this case you have allocated the object and thus have ownership of it. Then the nav controller takes ownership of it. When you pop the controller from the navigation stack, the navigation controller relinquishes ownership of it, but you never did, so it still has a retain count of 1 and won't get deallocated.

Relinquishing ownership of the controllers later in your code (like after dismissing the modal view) is a bad idea. It makes it difficult to analyze ownership when your releases are all over the place. As soon as the navigation controller has ownership you can release the object you allocated, as you do not intend to use it in the future:

- (void)didSelectSomethingInViewControllerOne
{
    ViewController2 *vc2 = [[ViewController2 alloc] init];
    [self.navigationController pushViewController:vc2 animated:YES];
    [vc2 release];
}

The situation above can have nothing to do with your problem. Your problem may reside in many different areas. Which is why troubleshooting memory management problems is difficult. Without seeing source code.

Upvotes: 1

Related Questions