views:

131

answers:

2

I have UINavigationController controlling several views. One of the views is composed of 20 scrollable pages. Each page is a constructed on the fly from UIViews by adding buttons, labels, UIImageViews etc. When this UIView is popped off the stack, the memory usage remains the same. Hence it keeps rising if I keep pushing/popping that view.

In my dealloc, I am traversing through all 20 pages and finding each type of object which got added via addSubview and then do a release on it but instruments says my memory usage never goes down! I am trying to use 'retainCount' to see what is up with objects I am releasing but I am perhaps not getting true picture via retainCount. For some elements retainCount shows 2 so I try to release that object twice but then app crashes. If I release it once it works but memory usage never go down :(

Q1: Do I need to traverse find each element and then do a release on that element ? Why can't I release a parent object and all objects contained by it would get released automatically ?

Q2: Is retainCount a reliable indicator ?

A: 

Are you sure that you are looking at net bytes? If you are accidentally looking at overall bytes, that will never go down. Net bytes is the current number of bytes allocated by your application.

When you release a parent object, it will need to dealloc everything it owns in dealloc:. If you release the main view there, that view will release all of its subviews if it is deallocated.

Also, retainCount is not usually a reliable indicator. Chasing down retain counts can be a daunting task due to the underlying nature of UIKit and Foundation. Many of Apple's classes will be retaining and releasing objects, and you will have no way to find out where and when this is happening.

rickharrison
Indeed looking at net bytes. I do perform release right after pushing the view on navigationcontroller. When back button is pressed I do this [self.navigationController popToViewController:[[self.navigationController viewControllers] objectAtIndex:[sender selectedSegmentIndex]] animated:YES]; could it be the popToViewController is somehow not releasing the current view ?
climbon
popToViewController will return an Array of the controllers that were popped. Try looping through that array and releasing all of those view controllers.
rickharrison
@rickharrison: doing that is a /very/ bad idea. Best to do the memory management properly upfront: c = [[UIController alloc] init...]; [navController pushViewController:c aanimated:YES]; [c release]; <-- release right after pushing
rpetrich
returned array contains just one view which is itself, obviously can't do a release on it. What do you really do in dealloc ? If I try to explicitly release a container UIView the app crashes but if I don't those same views are held up in memory.E.g there is a UIView object instruments say I had done a malloc in one place added it an array and also added it as subview to another object. Each time I do addsubview or addobject I do release upfront. Yet this object remains hanging. Releasing it explicitly result in crash. Seems very confusing.
climbon
Whenever you use addSubview: the view you are adding it to retains it. Then you release it so you don't have ownership over it anymore. Then, when you release the parent view, it will send a release message to all of its subviews. Similarly, when you release a view controller, you should release the parent view in dealloc: so that it can then release all of its subviews.
rickharrison
Do you mean I shouldn't release after an 'addSubview' or 'addObject' ?
climbon
A: 

Solved the problem. Here are pieces of the puzzles that baffled me for last whole week.

20 UIView objects were both referred by a UIScrollView and an array NSMutableArray. Releasing them from one wasn't releasing them fully since they were still referenced by the other. Made sure that after adding them to UIScrollView I call release on each UIView so retain count remains 1.

Each of those 20 UIViews were internally using an array passed to them from previous view -- via a simple pointer. After using objects inside the passed array I was releasing them also. So after fixing the retain count above when I finally came to release the whole view (via popping back to previous view) the app started crashing with messages like * -[CFString release]: message sent to deallocated instance 0x3ea6f00

Tracing them via NSStackLoggingNoCompact=1 I was being told that the there is some issue around the array I passed to the view I pushed on the stack earlier and which I just popped again. But I couldn't trace where. I did try to increase the retain on the whole array but that didn't help since I wasn't doing retain on the objects inside the array.

Anyway finally found the offending code where I was releasing objects from a passed array. I changed it to copy the contents of the array and now app is not crashing and all views are being released. Phew!

climbon