7

In new iOS 6, viewDidUnload is deprecated and we have been instructed to use didReceiveMemoryWarning instead, to manage objects in UIViewController instances and subclasses. Is it equally effective to assign nils to UIView kinds inside didReceiveMemoryWarning like the way it has been done inside viewDidUnload?

I am asking this because these two methods seems to be working differently. It seems like didReceiveMemoryWarning doesn't guarantee viewDidLoad to be called again to re-instantiate any necessary UIViews.

I suspect with iOS 6, memory management is done without requiring to manually deallocate UIView. Please help me to know what I have missed in understanding the lifecycle of UIViewController.

petershine
  • 3,190
  • 1
  • 25
  • 49

3 Answers3

13

My preferred method is now the following:

- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    if (self.isViewLoaded && !self.view.window) {
        self.view = nil;
    }
    // Do additional cleanup if necessary
}

Note that the test self.isViewLoaded is essential, as otherwise accessing the view causes it to load - even the WWDC videos tend to miss that.

If your other references to subviews are weak references, you don't have to nil them out here, otherwise you want to set them to nil, too.

You should get rid of viewDidUnload completely, and every code there should move to appropriate places. It wasn't guaranteed to be called prior to iOS 6 before anyway.

Eiko
  • 25,601
  • 15
  • 56
  • 71
  • 1
    Also, if this was an important thing to do, don't you think the base implementation would be doing it? – jrturton Oct 07 '12 at 16:02
  • You're right, it's not required. The amount of memory can vary greatly from a couple of bytes to dozens of megabytes for a sloppy implementation of image based views. So we can easily release it, but we don't have to. Especially with many controllers, it still may be a good idea, and the smaller the footprint, the more likely the app won't be killed in background. So my advise is more to nil it out *unless* you are sure it's cheap to keep. Setup cost needs to be considered, too, of course. – Eiko Oct 07 '12 at 19:16
4

In the iOS reference for viewDidUnload:, it states that this is deprecated for iOS 6 because

Views are no longer purged under low-memory conditions and so this method is never called

It doesn't say anything about placing this code in didReceiveMemoryWarning:. Since views are no longer purged under low memory conditions, you never have to worry about cleaning up your views in either method.

jrturton
  • 118,105
  • 32
  • 252
  • 268
Phil
  • 35,852
  • 23
  • 123
  • 164
  • 1
    This is the correct answer. Nilling out views is _not_ your concern as of ios6. – jrturton Oct 07 '12 at 16:01
  • 3
    viewDidLoad is not deprecated, viewDidUnload is. As for not niling out, I suggest watching the WWDC 2012 videos, where the speakers often recommend this. Again, it's not a must, but they clearly state to free as much memory as possible here (including the view). The documentation says the method is not called anymore, because people were abusing this method for other cleanup and often relying on it. So no, this answer is not correct. It is rather wrong. Apple has just given more control to the programmer. – Eiko Oct 07 '12 at 19:23
  • 2
    Surely "Views are no longer purged under low-memory conditions" means that you *definitely* have to worry about cleaning up your views in `didReceiveMemoryWarning:`? Otherwise views will not be released and memory usage won't be reduced. –  Oct 10 '12 at 14:08
  • 4
    Of course, I was probably misinterpreting what the docs were implying. [Joe Conway's blog on this topic](http://thejoeconwayblog.wordpress.com/2012/10/04/view-controller-lifecycle-in-ios-6/) explains *how* iOS 6 regains memory on `didReceiveMemoryWarning`, and *why* the views themselves are no longer purged. –  Oct 10 '12 at 14:19
  • @adamjansch If my bounty was the thing that drew the attention to this question, then it was the right decision to offer one. My thoughts were exactly as yours, and I still hardly believe how it's just unnecessary to call `viewDidUnload` anymore. Thanks for the blog post. – Mazyod Oct 15 '12 at 15:13
0

The answer by Eiko is not correct, and we should NOT set self.view to nil when receiving low memory warning. Doing so is useless and may be harmful.

iOS 6 will automatically freeing bitmaps of views which is not currently displayed, See http://thejoeconwayblog.wordpress.com/2012/10/04/view-controller-lifecycle-in-ios-6/ for details.

leafduo
  • 144
  • 1
  • 5