Do I set properties to nil in dealloc when using ARC?
Solution 1:
Short answer: no, you do not have to nil out properties in dealloc
under ARC.
Long answer: You should never nil out properties in dealloc
, even in manual memory management.
In MRR, you should release your ivars. Nilling out properties means calling setters, which may invoke code that it shouldn't touch in dealloc
(e.g. if your class, or a subclass, overrides the setter). Similarly it may trigger KVO notifications. Releasing the ivar instead avoids these undesired behaviors.
In ARC, the system automatically releases any ivars for you, so if that's all you're doing you don't even have to implement dealloc
. However, if you have any non-object ivars that need special handling (e.g. allocated buffers that you need to free()
) you still have to deal with those in dealloc
.
Furthermore, if you've set yourself as the delegate of any objects, you should un-set that relationship in dealloc
(this is the bit about calling [obj setDelegate:nil]
). The note about doing this on classes that aren't compiled with ARC is a nod towards weak properties. If the class explicitly marks its delegate
property as weak
then you don't have to do this, because the nature of weak properties means it'll get nilled out for you. However if the property is marked assign
then you should nil it out in your dealloc
, otherwise the class is left with a dangling pointer and will likely crash if it tries to message its delegate. Note that this only applies to non-retained relationships, such as delegates.
Solution 2:
Just to give the opposite answer...
Short answer: no, you don't have to nil out auto-synthesized properties in dealloc
under ARC. And you don't have to use the setter for those in init
.
Long answer: You should nil out custom-synthesized properties in dealloc
, even under ARC. And you should use the setter for those in init
.
The point is your custom-synthesized properties should be safe and symmetrical regarding nullification.
A possible setter for a timer:
-(void)setTimer:(NSTimer *)timer
{
if (timer == _timer)
return;
[timer retain];
[_timer invalidate];
[_timer release];
_timer = timer;
[_timer fire];
}
A possible setter for a scrollview, tableview, webview, textfield, ...:
-(void)setScrollView:(UIScrollView *)scrollView
{
if (scrollView == _scrollView)
return;
[scrollView retain];
[_scrollView setDelegate:nil];
[_scrollView release];
_scrollView = scrollView;
[_scrollView setDelegate:self];
}
A possible setter for a KVO property:
-(void)setButton:(UIButton *)button
{
if (button == _button)
return;
[button retain];
[_button removeObserver:self forKeyPath:@"tintColor"];
[_button release];
_button = button;
[_button addObserver:self forKeyPath:@"tintColor" options:(NSKeyValueObservingOptions)0 context:NULL];
}
Then you don't have to duplicate any code for dealloc
, didReceiveMemoryWarning
, viewDidUnload
, ... and your property can safely be made public. If you were worried about nil out properties in dealloc
, then it might be time you check again your setters.