For iOS apps, using ARC, do we typically release these in viewDidUnload
?
set all instance variables to nil
set all properties to nil
Release any context using CGContextRelease
, CGImage with CGImageRelease
, and color space with CGColorSpaceRelease
(releasing any non object)
no special attention needed for NSMutableArray
of NSSet
elements: just set the reference to NSMutableArray and NSSet to nil, and each element will be automatically released.
Will doing these handle most memory release under ARC? Are there other items that need to be released as well?
A lot of people misunderstand the point of viewDidUnload
. In particular, it is not the counterpart to viewDidLoad
. In most cases, your view controller will be deallocated without viewDidUnload
being called. For this reason, you should never consider a deallocation in viewDidUnload
a proper balance for an allocation in viewDidLoad
.
viewDidUnload
has been deprecated by Apple. Possibly the best argument against using it is its header (which I've wrapped):
- (void)viewDidUnload NS_DEPRECATED_IOS(3_0,6_0); // Called after the view
// controller's view is released and set to nil. For example, a memory warning
// which causes the view to be purged. Not invoked as a result of -dealloc.`
So what was viewDidUnload
? The idea behind it is that the view is being unloaded out from behind your view controller. This gives you a chance to detach any pointers to it and clear any information you can rebuild easily. Your view will probably be loaded back in, at which point you'll need to rebuild any caches. Apple describes this:
When a low-memory condition occurs and the current view controller’s views are not needed, the system may opt to remove those views from memory. This method is called after the view controller’s view has been released and is your chance to perform any final cleanup. If your view controller stores separate references to the view or its subviews, you should use this method to release those references. You can also use this method to remove references to any objects that you created to support the view but that are no longer needed now that the view is gone. You should not use this method to release user data or any other information that cannot be easily recreated.
Keep in mind that zeroing out references to objects in viewDidUnload
should be unnecessary now. If you're using ARC per Apple's recommendations, your view outlets are zeroing weak references. They'll automatically be nilled without you writing viewDidUnload
!
Further, clearing out caching information fits better into didReceiveMemoryWarning
, so you should probably write it instead:
You can override this method to release any additional memory used by your view controller. If you do, your implementation of this method must call the super implementation at some point to allow the view controller to release its view. If your view controller holds references to views in the view hierarchy, you should release those references in the
viewDidUnload
method instead.
Generally, the stuff people put in viewDidUnload
is better handled in viewDidDisappear
or dealloc
. The only thing left for viewDidUnload
is nilling any of your caches that can be rebuilt without data loss while the view controller is still open, when needed at some point after the view has been reloaded. (And, again, this should be handled in didReceiveMemoryWarning
.) These caches should be built lazily; when your app needs them again, it will quietly rebuild them.
So what should you do in viewDidUnload
? If you're using ARC: Nothing. Don't even write it. In fact, in the time since this answer was written Apple has deprecated viewDidUnload
.
For CGContextRelease
, the CGContext
resource is not an Objective-C object. (You pointed this out, but I want to repeat it for posterity.) As such, it can not be automatically deallocated by ARC. You are responsible for making sure it's deallocated and nilled just as with the old Manual Retain Release (MRR) memory management scheme.
If you put this code in viewDidUnload
, there is not guarantee it will ever be called. It must go in dealloc
. You could put it in viewDidUnload
as well, but…
And so:
dealloc
will usually be called without viewDidUnload
.The viewDidUnload has a tricky name, it is very easy to know what goes in there if you think about it properly.
First thing you have to know is that the iOS devices have a low memory handling method. This means that when the device needs more memory it will check which of its apps it can free memory from. It does this by calling the ViewDidUnload method (which might be improperly named).
So you are encouraged to set EVERYTHING that can be reconstructed to nil here. (Everything that you created in the viewdidload).
The exceptions are when you really cant afford to lose an object because of the time it might take to get the data or something.
If you do not implement this viewdidload your app will hold onto its items and objects and the iOS wont be able to free anything from it.
SO basically like I said, release (by setting the elements pointing to those objects to nil) everything that you can safely reconstruct in the viewdidload. (which will be called for sure after the view has been unloaded and wants to be loaded again)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With