3

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.

Jukurrpa
  • 4,038
  • 7
  • 43
  • 73

2 Answers2

5

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.

Buju
  • 1,546
  • 3
  • 16
  • 27
  • Well I do release every outlet in the dealloc method. But it has no effect as it is never called. I've tried to override release and retain, besides the fact that the retainCount reaches 50+ at some point (caused by the subviews?) it remains to 2 after the last release (when I've left the view). I don't see why it is so, as I only use it in the code I've posted. – Jukurrpa Jul 13 '10 at 10:20
  • That helped me fixing one of the remaining retains, thanks. I'm not using a NSTimer but I'm using a wrapper for ASIHTTPRequest which had DetailViewController as a delegate for some actions. I just had to release it when DetailVC viewDidDisappear is called. Maybe the last retain is due to something like this too, I'm going to keep searching. – Jukurrpa Jul 15 '10 at 12:46
  • I just did fix the second remaining retain by adding "self.target = nil" after releasing it in the wrapper I talked about before. (target being DetailVC, stored as an id with retain property). What could possibly explain this? – Jukurrpa Jul 15 '10 at 12:56
  • Hm, in fact that does not seem to be the solution. This randomly causes a crash when I leave the view... Damn memory management. Wouldn't auto/shared pointers be simpler? :( – Jukurrpa Jul 15 '10 at 13:41
  • HTTPRequest sound like you are using some kind of async operations? If thats the case, you should also be aware that when you are calling a target selector when your request did finish, that your target might just be released (maybe through closing the view) and your app will crash because you are calling something on a released object. – Buju Jul 15 '10 at 15:26
  • Yep that's for async http requests. But all requests are cancelled when I release it, so it doesn't call my VC's selector. Do you have any idea about the self.target = nil which lowers the retain count although I did a [self.target release] just before? – Jukurrpa Jul 15 '10 at 19:30
  • Oh right, I even came accross this while reading Apple's memory management documentation. Thanks. – Jukurrpa Jul 16 '10 at 11:32
  • I had this exact same problem all day today and had no idea it was my most recent edit causing the problems: the NSTimers :( Thanks so much for this post, it helped me a lot and saved me a LOT of time! – David Omid Jan 29 '13 at 22:13
2

I have seen this as well. As you pointed out, I haven't seen anything definitive in the docs, but my belief is that they are retained in memory until memory is needed. It makes sense from a performance perspective as doing so allows the app to quickly navigate between the different views.

Bottom line is, I wouldn't worry about it. You could fire off some Low Memory Warnings in the Simulator and see if it actually releases your VCs.

Jason McCreary
  • 71,546
  • 23
  • 135
  • 174
  • Thanks for your answer. I just tried sending a Low Memory warning in the simulator after creating and leaving about 10 VCs. All VCs viewDidUnload methods were called, but no dealloc at all! And, according to their addresses in memory, none seem to be reused, so memory usage keeps growing bigger. – Jukurrpa Jul 12 '10 at 16:41
  • I suggest taking a look at the Apple Developer Forum. You may find a much more detailed answer from one of the Apple DTS Moderators. – Jason McCreary Jul 12 '10 at 18:12
  • I've never been on this forum, I'll might take a look, thanks. – Jukurrpa Jul 13 '10 at 09:59