1

i'm facing a memory problem with my app,

I have a nav based app, if i push, pop and push all of my controllers the app will close due to memory overload.

I think it is what we call a retain cycle :

I have a custom nav controller : MyNavController, this Controller is my root controller, and push the main UIViewController : MyMainController, when the app starts the app use about 130 MB of memory, when i push a new controller : the memory goes up to 160 then i pop this controller : the memory is still 160 (159 exactly) then i push another view controller : the memory goes up to 190 MB ... The memory never goes down.

  • Can you confirm me that is a retain cycle ?

  • If i'm not wrong when i pop a view controller the memory should decrease of the view controller memory size ?

  • I always use strong into my properties (button, view, customView, customObject...) but when i set a breakpoint into my second level controller into the dealloc method i know that it is called, so the controller should be released ?

  • I have try something : i made an empty UIViewController and set the view in my xib to one of my non released controller so it could be more heavy than clear, so this controller have no line of code, simply a .h and .m with no custom code nothing, when i push this controller the memory goes up and when i pop it the memory does not go down ! I really do not understand what i have to look for, do i have to llok for on my MainViewController ? or in the controller i push on the stack ?

I simply load my controller using :

GeoControllerViewController *aGeoController = [[GeoControllerViewController alloc] initWithNibName:@"GeoControllerViewController" bundle:nil];
aGeoController.dictionnaryModele = _dicCours;
[self.navigationController pushViewController:aGeoController animated:YES];

Thanks in advance.

Vineet Singh
  • 4,009
  • 1
  • 28
  • 39
  • 1
    Why are you using a custom navigation controller? – Fogmeister Oct 17 '13 at 07:11
  • 1
    possible duplicate of [Retain Cycle in ARC](http://stackoverflow.com/questions/12802396/retain-cycle-in-arc) Memory problems are hard enough to debug with code. Just a description of the problem isn't going to be of much use in providing enough information to help you. – Abizern Oct 17 '13 at 07:15
  • You'll need to show some code too. i.e. what's inside the GeoController? – Fogmeister Oct 17 '13 at 07:16
  • There is so much thing inside GeoController and it is not the only one if i load an empty controller the same memory behavior appears. @Abizern i have so much code that i can't post anything on this forum. Fogmeisteri use a custom nav controller because i need to have orientation locked and orientation landscape only on my app. – Jacques Attali Oct 17 '13 at 07:22
  • You can lock down the orientations from just the project settings. Having a custom navigation controller that is, as you say, doing so much is also a code smell. – Abizern Oct 17 '13 at 07:25
  • No if you want some controller on portrait and some in landscape only you have to use a custom nav controller. – Jacques Attali Oct 17 '13 at 07:28
  • but that's not my problem right now. But thank you – Jacques Attali Oct 17 '13 at 07:28

2 Answers2

4

You ask:

Can you confirm me that is a retain cycle?

No. Could be a leak. Could be caching. Could be a retain cycle. We can't tell from what you've shared with us.

If i'm not wrong when i pop a view controller the memory should decrease of the view controller memory size?

Generally it should decrease when you pop, but if using a cache for anything, or if populating a shared model or what have you, it might not return entirely to memory levels prior to the initial push. Having said that, if there are caches in play, if you push and pop a number of times, the total "live bytes" that you see in allocations should return to a consistent level after you push and pop a couple times.

I always use strong into my properties (button, view, customView, customObject...) but when i set a breakpoint into my second level controller into the dealloc method i know that it is called, so the controller should be released?

If dealloc of that controller is getting called, that tells you that this is not involved in any retain cycle and that the memory associated with the controller will be recovered by the system. Theoretically, any of its strong properties should get released, too.

As an aside, usually your IBOutlet references (i.e. those things created by the NIB/storyboard) should be weak in an ARC project.


A couple of concrete bits of advice:

  1. Run your code through the static analyzer ("Analyze" on the Xcode "Product" menu) and make sure you have zero warnings there. If you have any, fix them first.

  2. Run your code through the Leaks tool in Instruments and see if it reports anything. If it does, that will tell you how to proceed.

  3. If you still can't find the issue, run the tool using the Allocations tool in Instruments, mark a heapshot/generation before going to the next scene, go to the next scene, return back, and mark another heapshot/generation. You can then analyze what was allocated and not released between those two moments in time, which will tell you what to then look for.

    See WWDC 2012 video iOS App Performance: Memory for some demonstrations on how to do this.

Community
  • 1
  • 1
Rob
  • 415,655
  • 72
  • 787
  • 1,044
  • Thank you very much Rob, my problem is when i use weak into my IBOutlet some view does not appears and do not load. So it might be my main controller that retains objects not the controller i load on the stack if the dealloc is called. – Jacques Attali Oct 17 '13 at 07:39
  • You talk about caching, caching is for all objects ? or only UIImage ? – Jacques Attali Oct 17 '13 at 07:40
  • @JacquesAttali `UIImage` is the most obvious candidate (esp since what's being cached is reasonably large). But you have other caches employed by iOS (e.g. `NSURLCache`, etc.). But when you run it through Leaks/Allocations, you'll find out what sort of objects have not been released, and rather than guessing, you'll be able to direct your efforts more constructively. – Rob Oct 17 '13 at 11:54
  • Well thanks Rob but i have tried something, i have set a new project an empty one, i set my nav controller and one controller i'll push on the stack with only stuff in the nib (images) no code, no properties no outlet and when i push back the memory does not goes down, does that means that the xib cache the image and never release it ? – Jacques Attali Oct 17 '13 at 11:58
  • @JacquesAttali Often you'll see it jump up and back down a bit, but not all the way. Do it again, it will jump up and back down back to it did i the previous step. Bottom line, if caches are the issue, you'll see it settle down after a couple of iterations. If it continues to grow, you have a leak somewhere. See that video for tricks for identifying the issues. – Rob Oct 17 '13 at 12:30
  • Thank you Rob, i have found the problem, when huge image are loaded in the xib the image are not released, i have to set the image to a nil string in the nib and load it in my viewDidLoad using imageWithContent. Thank you for ur time Rob. – Jacques Attali Oct 17 '13 at 13:27
0

Frankly, 130MB seems to be highly too much for a start in general.

  • I wouldn't be so sure about that. The question is: do you hold any references to the controllers besides the ones in navigation controller? It may be a leak as well. Why these controllers consume so much memory?

  • Yes, memory consumption should be lower.

  • I don't know if I get your question right. Usually strong properties are ok, but you have to be careful e.g. when two objects hold each other on strong. dealloc is called in ARC as well, so you can log out the moment when object is released.

Maciej Oczko
  • 1,225
  • 8
  • 11
  • Thank you Maciej, i know it is a lot but i have retina img, core animation and network request... it is a big app. Futhermore i use retina image on a non retina app (ipad mini) i certainly hold references but when i add an empty controller on the stack the memory goes up and does not go down. Thank for the second answer how can i know that two objects hold each other ? – Jacques Attali Oct 17 '13 at 07:27
  • Firstly check if you have strong property in each object that hold the second one. And you can play with Instruments as well [look here](http://stackoverflow.com/questions/9139619/arc-circular-retain-detection) – Maciej Oczko Oct 17 '13 at 07:31
  • i used instrument but there is so much object ! My question is can it be the main controller that retain object or the controller on the stack ? because when i load an empty controller the behavior appears – Jacques Attali Oct 17 '13 at 07:37
  • When controller is being pushed it is retained by navigation controller, but when when popped it is released. Your main controller should not retain it. – Maciej Oczko Oct 17 '13 at 07:46
  • @JacquesAttali Regarding your comment about there being so many objects in Allocations tool, two useful tricks: Stop the recording, click on the ⓘ button in allocations and you can filter the classes you see, and then re-record (make sure to turn off that filtering when you're done). Or just sort the allocations by class name – Rob Oct 17 '13 at 12:37
  • Thanks Maciej but i have found the problem : huge image loaded by the xib are not released... i have to set outlet and load image with imgWithContentOfFile... more consumming memory but released when the controller is no more on the stack ! – Jacques Attali Oct 17 '13 at 13:26