Memory Warnings

This post gives a quick intro to dealing with memory warnings in iOS.

I have to admit, I’ve avoided this subject for a looong time while learning iOS.  The first word says “these bugs will be incredibly annoying” and the second word says “you can just ignore these.”  Or rather, that’s what the back of your brain says while you’re just trying to get a new feature to work at all, before the planned code clean-up and polishing.

But you can’t ignore memory warnings, because it’s basically your last chance to open up some bytes before your app crashes.  And in the case of view controllers, if you ignore the viewDidUnload method, you can easily end up with dangling pointers to deallocated objects.  Not pretty!

The steps of a memory warning

This is what happens when your app gets a memory warning:

  1. Your application delegate receives a call to the applicationDidReceiveMemoryWarning: method.
  2. The UIApplicationDidReceiveMemoryWarningNotification is posted.
  3. For every view controller in memory:
    1. The didReceiveMemoryWarning method is called, and,
    2. in some cases:
      1. The view of the view controller is released and set to nil, and
      2. The viewDidUnload method is then called.

Through experimentation, it looks like your view can be unloaded when both:

  1. Your view is not in the view hierarchy, and
  2. Your view controller is not owned by container controller, such as on the stack of a UINavigationController.

Ways you can respond

(1) Release and set any UIView pointers to nil in viewDidUnload.

At bare minimum, you should always respond to the viewDidUnload method.  This is because your view is clearly not needed, and the system now regards your view as being released.  If you had strong pointers to any view objects, you can save memory by releasing them.  If you had weak pointers to objects only retained as a subview of self.view, those objects are now released, and you should set those pointers to nil.

(2) Release any cached data in the other methods.

Most of the other methods are hooks you can use within each receiver class to drop non-essential data.  For example, if you have any UIImage pointers, it would be wise to release them and set them to nil.  If the image is currently visible, it will be retained by its UIImageView object.  This same idea holds for NSData of sound bytes or any other data structure of significant size or quantity.

A weak pointer view strategy

To easily work with the possibility of viewDidUnload being called, I like to consistently use weak pointers (non-retained pointers) to all view objects in a view controller.  This way, if the view is released by the system, all subviews are also released, since they are only retained by their superviews.  The only responsibility with this strategy is to set your view pointers to nil in viewDidUnload, and to be aware that, unless you release your view controller as soon as it is out of the view hierarchy, your view pointers may be nil.  This last consideration is usually taken of since messages (i.e. method calls) sent to nil are fine.

Post a Comment

Your email is never published nor shared. Required fields are marked *