Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are 'dealloc' and 'viewDidUnload' methods still required when using ARC, pre-iOS6?

I work as part of a large team working on iOS legacy code with a target iOS environment of 4.3 and later. I have seen other developers check in classes that descend from NSObject but do not have a dealloc method. I have also seen UIViewController descendants that do not include viewDidUnload methods. When I ask about this code the usual response is "Don't worry, ARC takes care of that now."

I understand that viewDidUnload is called when iOS experiences low memory conditions, with a goal of freeing up memory by releasing objects that can be recreated by calling viewDidLoad, and that dealloc is called when the retain count of an object hits zero. For UIViewController objects and descendants this can mean that 'viewDidUnload' may or may not be called before dealloc.

So here's my question: Are dealloc and viewDidUnload methods still required when using ARC on iOS versions prior to iOS 6?

If the answer is "Yes!" then I will need good reasons and/or documentation to carry the argument.

Looking forward to your responses. (With thanks to Tommy for helping me tighten up my question.)

like image 750
RGoff Avatar asked Sep 27 '12 21:09

RGoff


2 Answers

viewDidUnload is deprecated. So regardless of ARC you not only don't need one but shouldn't use one. The stated justification is that views aren't purged on low memory warnings any more (presumably because they now contribute too little to the total to be worth the responsiveness hit); I wouldn't be surprised if part of the justification were that a lot of people assumed they could release all resources created in viewDidLoad within viewDidUnload and that alone would prevent leaks. That isn't true because viewDidUnload is called only if the view is unloaded because of a low memory warning. It isn't called in the normal lifecycle.

Under ARC's new rules:

You may implement a dealloc method if you need to manage resources other than releasing instance variables. You do not have to (indeed you cannot) release instance variables

EDIT: to comment on 4.3+ specifically...

ARC won't implement a version of viewDidUnload for you. The point of the viewDidLoad/viewDidUnload cycle was that if you retain any part of the view hierarchy for any reason then you'll cause that not to be released automatically upon a low memory warning, but doing so won't buy you any benefit because as soon as the view is next loaded whatever you retained will be replaced with a new copy. So if you have strong IBOutlets to views that are within the hierarchy underneath self.view anyway then ideally you'd nil them out during viewDidUnload. Even if you have weak references that's a good place to prevent yourself from carrying forward any dangling pointers.

As of iOS 5 you can have self-zeroing weak references so using those and not implementing viewDidUnload would be the way to go if you were supporting 5+. For 4.3 if you use strong references and omit viewDidUnload you may end up preventing as thorough a response to a low memory warning as Apple would like but you won't leak memory. If you use weak references then you'll need to be a bit careful about not referencing any of those objects at times when you might not have a view (ie, any time you're not on display but the view has previously loaded — setters on the controller that also adjust a view but which are affected by another are a classic example; like say if you were updating a field by key-value observing).

You can use the simulator's 'Simulate Memory Warning' to test and debug that stuff to an extent.

The dealloc that ARC provides will be the same regardless of iOS version. However it'll cover only Objective-C objects. When they say you can't release instance variables they mean it in the very literal sense of send the release message to them. Supposing you have Core Foundation objects or have performed pure C memory allocation then you'll want to implement a dealloc that disposes of all of those.

Obviously Instruments and the Leaks tool are the ways to test and debug that area; be careful any time memory is leaked to check whether the type of object that created that memory is also being leaked. The immediate object can be fine but its allocations will appear on the leaked list if it didn't dealloc because somebody else leaked it.

like image 113
Tommy Avatar answered Oct 06 '22 23:10

Tommy


viewDidUnload is now deprecated and is no longer called by the system (as of iOS 6). It was never quite as useful as Apple hoped, and was more trouble than it was worth. This has nothing to do with ARC.

dealloc is often not required under ARC, but still is necessary in situations where you need non-ARC resource management. For example, if you need to use free(), or otherwise release a resource. It is also a good place to remove yourself as an observer or delegate. But many classes now do not require dealloc.

like image 31
Rob Napier Avatar answered Oct 06 '22 22:10

Rob Napier