how to release objects in programs based on UITabBarController? - iphone

I want to release objects in my programming based on UITabBarControllers, all tab bar items launches together at once,
so what should I do for this??

Just release all what you retained. I think dealloc will be called when necessary.
Maybe this will help you a bit:
Dealloc not called for ViewController; it's about why dealloc is not called when using UITabBarCtrlr.

You can still release anything that you retained, you don't have to do it in dealloc. Just recycle anything anywhere that you want to, and set the object to nil. In dealloc, don't release anything that is nil so you are safe. However, your UITabBarController might still assume the validity of the objects, so it's up to you for implementing the logic.
If possible, you should just allocate a new UITabBarController.

Related

Memory management when using IBOutlet/NIBs

My app is nearly finished and I have been Profiling it using Instruments. I'm checking out retain counts of various objects.
I have been careful to release any objects which I have called alloc on, and these don't seem to be leaking - so thats cool.
However, I have a view controller which has a UIPickerView in it. I set that up by dragging it onto my NIB in IB, defined the property using IBOutlet, synthesized it, and then hooked it all up.
Every time I launch the view, it seems the number of UIPickerViews increases by one. I was under the assumption that I do not need to release this kind of thing myself, as I had assigned it to a property (using nonatomic, retain).
This is happening to all my UI stuff - buttons etc, not just the picker view. I was just using that as an example.
Can anyone help me out here?
Thanks!
When the view is loaded all the items created from the NIB are retained for you and your IBOutlet pointers are initialized pointing to those retained subview objects. You need to release those in viewDidUnload. Are you doing that?
In viewDidUnload you should release all objects created from the NIB and set those pointer to nil. You should also release those same object in dealloc. Example here.

memory management with outlets and properties in view controllers

Hey guys, sorry for beating the memory management (dead)horse again. I know this question has been asked several times on SO, but I feel all the threads out there is still lacking two pieces of information. Let me put forth what I DO know to save everyone some time.
1) When you create an IBOutlet, your view controller automatically retains this outlet.
1a) When you don't create an outlet, the 'framework'(the nib?) releases your objects(like uilabels or uiviews) for you.
2) When you do self.myOutlet = nil, you effectively release an outlet(providing that you have synthesized your properties correctly). This is because the setter releases the outlet and assigns it to nil.
What I don't know:
1) The MAIN question: If you do self.myOutlet = nil in viewDidUnLoad, do you still need to do anything in dealloc? Can you make the assumption that viewDidUnload always called before dealloc?(and therefore your retained views are released?)
2) If you don't synthesize a property for that outlet, what happens? Shouldn't the framework release it automatically?(since you don't have a retain property) If you do have to release it, how do you do it and where(in viewDidUnload or dealloc)?
If anything is wrong, please point it out to me. Any clarifications at all would be very helpful.
(#1) The Apple docs say to do both
In addition, because of a detail of the implementation of dealloc in UIViewController, you should also set outlet variables to nil in dealloc:
http://developer.apple.com/library/ios/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmNibObjects.html
(#2) If you don't synthesize a property, you still need to make a property, and it better retain -- read the link. The UI object is created, autoreleased and the outlet property is set (which is supposed to retain). There is no release called for you because they already did the release they were supposed to do -- you retained, so you have to release (in both viewDidUnload and dealloc)

When should I release an object in dealloc?

Sometimes when coding in Objective C for the iPhone I wonder if I should release an object in dealloc or is it sometimes better to release in viewWillDisappear if that view is a separate rarely used part of your app.
Thanks.
Well first off, you probably want to release things in viewDidDisappear: (after they are off screen), not viewWillDisappear: In any event, you should probably release it in both viewDidDisappear: and dealloc ...
In viewDidDisappear: you should release anything you don't need while you are off screen in order to save memory. In dealloc you should release everything your object could possibly have retained. You want to do this regardless of whether you potentially released it in viewDidDisappear:, in case your code entered through a weird path where viewDidDisappear: is not called. That might happen in the future when you reuse the view controller in a different context, or when Apple changes something about the collection view controllers you are housing your VC in.
So long as you are appropriately nil-ing out the ivars after you release them (which should be automatically happening if you are using properties) then over releasing will not be an issue because if you release it in both places the second release will end up sending the release message to nil.

Cannot allocate new instance of UIView subclass after deallocating

I have an instance variable *TangramLevel(:UIView) currentLevel; in my viewController class, and I have an instance allocated at start (it's retainCount 1). I attached it to the view [self.view addSubview:currentLevel]; (retainCount 2).
When the level finishes, it notifies the controller, so controller removes it from the view [currentLevel removeFromSuperview]; (retainCount 1), and release the allocated instance - [currentLevel release]; -, to have it deallocated (retainCount 0 = invoke dealloc).
Then on the next line, controller wants to allocate/addSubview a new level instance with another level data, but the application crashes (EXEC BAD ACCESS).
If I don't release currentLevel after removeFromSuperview, the appliaction works, but I have an unused level instance left in memory then, which is also a problem (the main problem itself).
Is there any bug in the method I wrote above? Or the bug is elsewhere, maybe in the level class? I allocated some UIImageView in the level, but I release every allocated object in the levels dealloc method. Any ideas?
Post your code.
This is definitely a memory management issue. The question is "where is the problem created?" To answer that, we need to examine the following:
Your "currentLevel" iVar handling code (do you used synthesized properties, etc.). Post it.
How are you assigning the view to currentLevel?
Where are you releasing this, specifically?
How is your view's dealloc implemented (what do you release and how)?
Is there any other code that retains/releases this view or anything related to it?
The fact that you're calling release in your "I'm done with this level, let's swap in the next" code suggests an overall design issue. Make the memory management of each of a class's iVars the responsibility of its accessors and ONLY use the accessors to interact with it (even from within the class/instance). With synthesized properties, this makes it brain-dead-simple. That way you don't have to worry about where to retain/release iVars because it's always funneled through the accessors.

What sort of cleanup work should I do aside from dealloc in an iPhone app?

Right now, I do most of my cleanup work in dealloc (cleaning up IBOutlets, allocated objects, etc.). What other places should I do cleanup work in order for my app to be a well-behaved one? Could you explain the things that are typically done in those methods as well?
For example, viewDidUnload, applicationWillResignActive, etc.
For views, I typically release any UI widgets that were created from the NIB file in viewDidUnload. Any models or other objects I clean up in the viewController's dealloc.
Sometimes I have views that create a model (say a Dictionary of section names to section rows) from a primary data object. If I create/build an object in viewDidLoad I will release it in viewDidUnload (since my viewDidLoad will get called again when the time is right).
I believe that in SDK 3+ you don't have to typically worry about implementing didReceiveMemoryWarning directly as the new viewDidUnload method is the main place to do your view cleanup.
For normal objects (objects without special life cycles like a view controller has) I just release their member vars in the dealloc.
Don't forget:
- (void)didReceiveMemoryWarning
Note: This "Answer" is only relevant to app quit/termination.
According to the answer I received to my question, it's not even necessary at all to do cleanup work like cleaning up IBOutlets, allocated objects, etc. Just save state (as necessary) when your app quits, and let the iPhone OS handle the final cleanup.
Note that your question is ill-formed. The -dealloc method of UIApplication is never called. The -dealloc of your application's delegate is never called. That means that any objects that are retained by your application's delegate will never be released, so their dealloc is never called.
You should be doing your cleanup in your application delegate's applicationWillTerminate:
Since your application is about to die, you don't really need to do anything except give back non-memory resources, make sure your data files are properly closed, and that your NSUserDefaults are synchronized so you can restart properly the next time you are run.
However, any object that might be allocated and deallocated repeatedly over the life of the program deserves a proper Obj-C dealloc method, as documented by Apple, and it is good practice to write this for all your classes, even though they won't be called, just so you build good habits, and readers won't be confused. Also, it saves maintenance headaches in the future, when you DO create and destroy multiple of these, for example in your unit tests.
I would use the [yourObject release] method, but replace yourObject with an object