Memory management when using IBOutlet/NIBs - iphone

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.

Related

How to properly compose a "viewDidLoad" method

I'm not entirely new to iPhone dev, but I ran across a situation where I was unsure about the best design choice for my code.
I have a view controller which asynchronously fetches an image from the internet and loads it into an image view. When the app receives a memory warning however, the imageView is released by didReceiveMemoryWarning. If the app receives a memory warning while loading an image, the imageView is nil by the time my code tries to load the image into the imageView.
What is the best practice for viewDidLoad? Should I just instantiate any variables that I may need later on? Or should I just check for nil values elsewhere in my code?
Also, in viewDidUnload, should I just set IBOutlet variables to nil? Why is this?
Thanks! -Matt
Why not just create the image view on demand when the image is loaded? No need to create it any earlier. Or, if you do, then just have code to recreate it if it has been released.
In viewdidunload you should release resources that you created in viewdidload (or load view). Including any IBoutlets that interface builder hooked up for you. It's good practice to set these variables to nil to ensure they won't be inadvertently accessed after release, or double released.
IBOutlets can be both instance variables and properties. In both case, we should release the references when the view, which is top most superview, is unloaded. Setting the IBOutlet retained properties to nil releases the reference automatically, but for instance variables we need to release them. We still need to set instance variables to nil because viewDidUnload is not dealloc, so we must comply with the managed memory rule or we might have invalid references sitting around inside the instance.
I don't think there are rules about what you should do in viewDidLoad, but if you did release and set some variables to nil in viewDidUnload, you need not have to check for nil again in the viewDidLoad unless you don't trust the framework.

When I use a .xib file to layout my viewController IBOutlets aren't being released when the view controller is released

I use a .xib to layout my viewController and have 10 IBOutlet objects that IB uses, none of them have #properties assigned to them (no #property(retain) IBOutlet...). When I release the viewController none of those objects are being released, I have to manually release them in the dealloc of the viewController.
This doesn't seem like normal behavior, I thought that those objects would be released by the system since IB is whats assigning them, what could I be doing wrong?
Apple's Memory Management Programming Guide tells you exactly how to properly release IBOutlets.
In short, you are supposed to release them in dealloc, but you also want to release them in viewDidUnload.

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)

iphone memory management (basic)

Very basic question about iPhone memory management:
Say I have a viewController with several subviews also controlled by viewControllers. When I remove the top viewController and release the instance - what happens to its children? Are all the therein contained objects released as well?
When I run my app in instruments, I don't get any memory leaks. But the value for «all Allocations» goes up and up? (I assume that this value is the overall memory consumed by my app?)
View controllers release their view on dealloc. Views release their subviews on dealloc. A release is not a dealloc.
What's retaining the other view controllers? If your view controller is, then your view controller should release them. Usually this'll be a property, so you can do self.subViewController = nil.
Additionally, if you have any IBOutlets (and I really hope you're using properties for these), you'll also have to set them to nil in dealloc.
Release what you own.
It depends where your child UIViewControllers are referenced. If they are only referenced in the root view controller (retained when they are created and released on dealloc), then they will be released when it is deallocated. If you have other references to those view controllers (from your app delegate perhaps?), they will only get released when those references are released.
Cocoa touch NSObjects are reference counted, they are released when their retainCount is decremented to zero. The retainCount is decremented whenever release is called on an object.

do I have to release IBOutlets in -(void)viewDidUnload?

They say:
// Release any retained subviews of
the main view. // e.g. self.myOutlet =
nil;
I've never seen that previously. so I wonder if they talk about nib outlets here?
Similar to how anything you allocate in init should be unallocted in dealloc.
If you alloc memory in viewDidLoad, you should release it in viewDidUnload.
The issue gets confusing when you bring nib files into the picture. If you are manually loading the nib file, you should manually unload it and set all the IBOutlets to nil.
You don't have to if there is a reason to keep it around, but assuming you need to access the entity point to via the outlet if the view has been torn down then yes, you should release. Otherwise your view controller will be asserting a retain against all of the IBOutlets from yoour nib even though the nib itself has been unloaded, which prevents them from being dealloced. Since these objects may have textures and such backing them, and the iPhone uses main ram for video that can add up to a lot of wasted memory very quickly.
Additionally, if viewDidLoad is called again then a new object will have been created and assigned to that outlet when the nib is reloaded, so if you use it anywhere else (set properties in other objects to the object pointed to by the IBOutlet) then your app might end up in an inconsistent state.