Iphone – didReceiveMemoryWarning and viewDidUnload

iphonememory-managementuiviewuiviewcontroller

From Apple's View Controller Programming Guide / Managing Memory Efficiently;

didReceiveMemoryWarning

Use this method to deallocate all noncritical custom data structures associated with your view controller. Although you would not use this method to release references to view objects, you might use it to release any view-related data structures that you did not already release in your viewDidUnload method. (The view objects themselves should always be released in the viewDidUnload method.)

viewDidUnload

You can use the viewDidUnload method to deallocate any data that is view-specific and that can be recreated easily enough if the view is loaded into memory again. If recreating the data might be too time-consuming, though, you do not have to release the corresponding data objects here. Instead, you should consider releasing those objects in your didReceiveMemoryWarning method.

http://developer.apple.com/library/ios/#featuredarticles/ViewControllerPGforiPhoneOS/BasicViewControllers/BasicViewControllers.html

  1. For didReceiveMemoryWarning, we are recommended to deallocate non-critical data structures. So, what is critical and what is non-critical?

  2. Also, it says to release what we did not already release in viewDidUnload.
    But when there is a memory warning didReceiveMemoryWarning is called and view could be unloaded then viewDidUnload is called. So, is it talking about the moving those codes to the former event's method(didReceiveMemoryWarning) or am i missing something about the order of events?

  3. For viewDidUnload, we are recommended to care about easily recreating the data when reloading a view.
    So, if a view is in use and could not be unloaded, why will we release time-consuming data in didReceiveMemoryWarning? After those data released, when user tries to do something within the current view, then it will be time-consuming to load them too.

Best Answer

First of all, these are just guidelines, so if you don't think it makes good sense to release something in didReceiveMemoryWarning then don't do it. But keep in mind that if your application is the one that is causing the memory warning in the first place then it will eventually just be terminated by the OS.

Re (1): Critical vs. non-critical is entirely your call. Only you can really determine what data you're holding that you consider critical. Though it's probably going to be closely related to your (3), that is, something that is easily recreated is probably not too critical.

Re (2): I don't think the statement is in reference to the order of the calls. As you have realized, in general, viewDidUnload is going to get called after didReceiveMemoryWarning (since didReceiveMemoryWarning can cause viewDidUnload to be called). As an example, in viewDidUnload one will release references held to UI elements from a nib. So don't also release them in didReceiveMemoryWarning.

Re (3): If a view is in use and thus can't be unloaded, then yes, obviously it doesn't necessarily make much sense to release it in didReceiveMemoryWarning. However, you may actually have instances where a view couldn't be unloaded, but is known to not be visible (not terribly normal), in which case it might make sense to unload it's data and recreate it when the view is visible once again.

Additionally, I agree the "Instead, you should consider..." remarks are a bit odd, but again I think the point of recommending the data be released in didReceiveMemoryWarning stems from the fact that if you're receiving those warnings then your own app might be in danger of being terminated. So while it is currently the case that viewDidUnload probably is always called as the result of a memory warning, that may not always be the case in the future and so conceptually it makes more sense to release the data in didReceiveMemoryWarning itself. In didReceiveMemoryWarning you KNOW there is memory pressure, in viewDidUnload you may not. So while it's true that the data will then be expensive to recreate, that might be better than having your app terminated. To the user it will appear as though the app crashed.

My own personal approach to those methods is generally this:

  • viewDidUnload - Release any references to UI elements loaded from a nib. Release any UI elements I created myself in viewDidLoad.
  • didReceiveMemoryWarning - Release any data that is used in the presentation of the UI that I can recreate if/when viewDidLoad is called again (or some other app specific event). Do NOT release anything that I can't possible recreate.
Related Topic