Dealing with Low Memory Condition in iOS View Controller

The way low memory situation is handled by a UIViewController has changed in iOS 6. Developers need to be aware of it. Here is a summary of the situation.

Prior to iOS 6, under low memory situation a UIViewController that is not visible will unload (destroy) all its child views. Then viewDidUnload method is called. From that method, the application should free up any internal state. This state was then recreated from viewDidLoad if the controller becomes visible again. From this method all views needed to be reinitialized with data.

As of iOS 6, the behavior has changed. The OS no longer unloads the child views. Instead, it destroys internal objects like graphics context and backing stores that take up more memory than the views. Also, viewDidUnload is no longer called. Instead, didReceiveMemoryWarning is called. You will need to free up any application held state from there. This state can be recreated from viewWillAppear. Just as before, you will also need to re-initialize the views from this method with fresh data.

Here is an example. Here, the controller has a NSArray to store application state. It has a UIScrollView as the root view.

@interface VideoListController : UIViewController
@property (strong, nonatomic) NSArray* videoList;
@property (strong, nonatomic) IBOutlet UIScrollView *scrollView;
@property bool listDirty;

- (void) didReceiveMemoryWarning
    //Must call super's method. It does important clean ups.
    [super didReceiveMemoryWarning];

    // Dispose of any resources that can be recreated.
    self.listDirty = true; //Mark state as invalid
    self.videoList = nil; //Free state data

- (void) viewWillAppear:(BOOL)animated {
    if (self.listDirty) {
        //Fetch data and initialize views

        //Mark the state as valid and current
        self.listDirty = false;
    } else {
        NSLog(@"Showing old video list");
- (id) init {
    self = [super init];
    if (self) {
        //Mark state as invalid
        self.listDirty = true;
    return self;    

The viewWillAppear method performs all the hard work of fetching data (from a server or database) and initializing the views. However, you don’t want to do that at all times. This is why we are using the “listDirty” variable. If the state is invalid or uninitialized, the listDirty flag is set to true. Only then we retrieve data and initialize the views.

The controller will now behave as follows:

  • When the controller is created for the first time, the init method flags the state as dirty. This will cause viewWillAppear to retrieve data and initialize the views.
  • If the controller is in the background (not visible) and memory runs low, then didReceiveMemoryWarning will be called. From there we are freeing up internal state data and marking the state as dirty. If the controller becomes visible again, viewWillAppear to reload the data.
  • If the controller is in the background, but the device doesn’t run out of memory, then the controller keeps the state data. When it becomes visible again, viewWillAppear will be called but will not reload any data.

Normally, you should not need to free up any data from viewWillDisappear. Only if a controller maintains a large amount of data then you may consider freeing it when its root view gets hidden. In that case, you can migrate the code from didReceiveMemoryWarning to viewWillDisappear.

I can provide a few guidelines:

  • Do not fetch data and initialize views from viewDidLoad. Generally speaking, eliminate viewDidLoad method from your application. Perform initialization from viewWillAppear. If you have an app developed prior to iOS6, you will need to migrate the code from viewDidLoad to viewWillAppear.
  • Keep a flag that will tell you if data is already loaded and available so you don’t perform unnecessary work from viewWillAppear.
  • Free up any internal state from didReceiveMemoryWarning. If you have an app developed prior to iOS6, you will need to migrate the code from viewDidUnload to didReceiveMemoryWarning.

One thought on “Dealing with Low Memory Condition in iOS View Controller

  1. Thanks for clarifying this. I have been searching for this explanation. However, there is one problem that I am facing. Suppose I have a UITableViewController which is currently visible and my app receives the didReceiveMemoryWarning. Here I set my objects being used in the table view to nil so that ARC can clean the memory up.

    However, now my “visible” UITableViewController will stop working because the data has been cleared and viewDidAppear hasn’t been called yet.

    Shouldn’t it be the case that didReceiveMemoryWarning should not be called for the View Controller which is currently visible? How do you handle this?

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s