36

There is a similar question to this on SO here, however I just want to clarify something that wasn't fully explained there.

I understand that all delegates and outlets - in fact any reference to a "parent" object, to be a good citizen and think about the object graph for a minute - should be zeroing weak references. Due to the nature of zeroing weak pointers automatically dropping to nil on the referenced object's retain count reaching zero, does this mean that setting IBOutlets to nil in viewDidUnload is now unnecessary?

So, if I declare my outlet like so:

@property (nonatomic, weak) IBOutlet UILabel *myLabel;

Does the following code have any effect?

- (void)viewDidUnload
{
    self.myLabel = nil;

    [super viewDidUnload];
}
Community
  • 1
  • 1
Stuart
  • 36,683
  • 19
  • 101
  • 139

5 Answers5

15

Just doing a bit of research...

As I understand it, weak is similar to assign, in that they're both weak references.

However, assign does not create a zeroing reference. i.e. if the object in question is destroyed, and you access that property, you WILL get a BAD_ACCESS_EXCEPTION.

Weak properties are automatically zeroed (= nil) when the object it is referencing is destroyed.

In both cases, it is not necessary to set property to nil, as it does not contribute to the retain count of the object in question. It is necessary when using retain properties.

Apparently, ARC also introduces a new "strong" property, which is the same as "retain"?

Research done here

Andrei Chevozerov
  • 1,029
  • 1
  • 10
  • 24
Daryl Teo
  • 5,394
  • 1
  • 31
  • 37
  • 1
    Thanks for the response. I understand the workings of the weak reference, my question is more relating to the mechanisms underlying `viewDidUnload`. In other words, is it always the case that the view will force the weak reference to `nil` directly following the `viewDidUnload` call? – Stuart Oct 07 '11 at 03:39
  • 2
    Again, **as I understand it**, the View and its SubViews will be released when it is removed from display. Since, weak doesn't increment release count, and gets zeroed when its reference is destroyed, it should not necessary. – Daryl Teo Oct 07 '11 at 03:46
  • 1
    Sorry, I must have missed that part of your answer when I read it the first time. – Stuart Oct 07 '11 at 12:16
11

I did a little testing and it appears that the code in the viewDidUnload method is unnecessary. To support this, the docs for viewDidUnload do actually say:

By the time this method is called, the view property is nil.

Indicating that the weak reference must have been set to nil automatically.

Stuart
  • 36,683
  • 19
  • 101
  • 139
  • 3
    This is also my understanding. But why then does Xcode insert `[self setMySubview:nil]` statements in `viewDidUnload` when creating weak outlets? – Yang Meyer Jan 24 '12 at 09:29
  • 2
    I think it _could_ be a feature that is left over from pre-ARC code, in the same way that when you ask Xcode to generate a `NSManagedObject` subclass for Core Data the generated properties are set to `retain` instead of `strong`. Although in the case of the outlets they _are_ created as `weak`. My guess is that it's unintentional. – Stuart Jan 24 '12 at 10:18
  • I agree. the Interface Builder UI is likely erring on the side of caution when dragging-and-dropping to create outlets in code. Those nil settings can be safely removed as long as you're using ARC and weak referencing on the outlets in question. – Joe D'Andrea Jun 27 '12 at 02:07
5

I have some empirical evidence to support that IBOutlets are indeed already set to nil automatically. Here's what I did:

  1. I set up explicit ivars for my IBOutlet properties (@synthesize myLabel = myLabel_) so that I may later inspect their values in the debugger.
  2. I enabled a breakpoint on the first line of viewDidUnload.
  3. I arranged for viewDidUnload to get called by simulating a memory warning.
  4. I inspected the values of the explicit ivars that I associated with my IBOutlet properties.

The explicit ivars all had nil as their value then I hit the breakpoint.

Emile Cormier
  • 28,391
  • 15
  • 94
  • 122
3

From my understanding of how the outlets are managed in ARC if you are using a weak reference, you do not need to add anything to viewDidUnload as it will already be nil. Doing so is thus redundant.

However if you do have strong outlets, which apple says you should do if you are pointing to a top level item in the nib, then you should definitely continue to add the appropriate line in viewDidUnload to nil out these ones.

scottbates22
  • 326
  • 1
  • 6
  • I want to know, if i defined this `@property (nonatomic, strong) IBOutlet UILabel *myLabel;`, do i need define `self.myLabel = nil;` in function `viewDidUnload`. – BlackMamba Sep 16 '13 at 02:30
0

Starting from iOS 5 and OS X 10.7, weak will produce an automatic zeroing pointer. This means that when the pointed object is release, the pointer is automagically set to nil (for details see Zeroing Weak References in ARC).

So, under iOS 5+ and OS X 10.7+, it is not useful to set the weak IBOutlet properties to nil manually in the viewDidUnload method: when the main view is unloaded, all its subviews will be released, so the related properties are set to nil.

Community
  • 1
  • 1
MonsieurDart
  • 6,005
  • 2
  • 43
  • 45