6

Just starting out with ARC. Pre-ARC, I would just simply declare my outlets as for example: IBOutlet UIButton *button; so I am not retaining it or anything. With ARC, not specifying weak or strong implies strong.

So if I do the same thing under ARC (i.e. IBOutlet UIButton *button;), does this mean button is a strong reference? or Do I have to explcility define it as weak?

In short, does IBOutlet imply __weak?

Ben Lings
  • 28,823
  • 13
  • 72
  • 81
0xSina
  • 20,973
  • 34
  • 136
  • 253

3 Answers3

16

The word IBOutlet is actually defined as nothing:

#define IBOutlet

Xcode just uses the presence of this word in your code for purposes of allowing you to make connections in Interface Builder. A declaration of a variable or a property as an IBOutlet:

IBOutlet UIButton * button;
@property (...) IBOutlet UIButton * button;

therefore doesn't have any direct effect as far as ARC is concerned; it doesn't (although, conceivably, it could) translate into __weak or anything like that. The word itself is entirely gone from your source by the time the compiler gets it.

On the other hand, the fact that this variable or property is an outlet does have a meaningful effect on how you need to think about the memory management.

The implicit storage qualifier for an object variable declaration like IBOutlet UIButton * button; under ARC is __strong, as you said -- any object assigned to the variable will be considered "owned". Under MRR, the declaration is just a pointer; assigning to has no effect on the reference count/ownership of the assigned object -- it acts in the same way as an assign property.* So the meaning of the same ivar declaration changes between the two management systems.

Objects in a xib have owned/owner relationships that are formed by the view hierarchy; that is, parent views own their subviews. The top-level view in a xib is owned by the object known as File's Owner. This setup means that, generally speaking, your outlets to objects in an xib that are not top-level should be weak (under ARC) or assign (if a property under MRR). They are not owning relationships; they are essentially convenient indexes into the view list. This is Apple's recommendation:

...you don’t need strong references to objects lower down in the graph because they’re owned by their parents, and you should minimize the risk of creating strong reference cycles.

[...]Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create should will [sic] therefore typically be weak by default...

Your simple pointer IBOutlets, as I explained, acted -- for memory management purposes -- like weak properties,** which means that they were doing the right thing. The same declaration becomes probably the wrong thing when compiled under ARC.

In summary: IBOutlet does not translate into weak, but it does change the meaning of the pointer. Since the default memory management semantics of IBOutlet UIButton * button; change from "assign" under MRR to "owned" under ARC, and since IBOutlets should generally be non-owning, the presence of IBOutlet does indeed imply that the pointer should be declared __weak under ARC.


*And similar to a weak property -- the only difference there is that weak pointers are set to nil when the object is deallocated.

**Except for the auto-nil part.

Or, really, it should be a weak property.

Community
  • 1
  • 1
jscs
  • 63,694
  • 13
  • 151
  • 195
  • Thanks, it's much more clear now. But one thing I am confused about is : Even if I don't explicitly define the IBOutlet as __weak (in which case it will be strong), wouldn't ARC take care of it? As long as there's no retain cycles (and there aren't any), everything is taken care of, no? – 0xSina May 04 '12 at 12:42
  • ARC will continue to do what it does, so, yes, as long as you avoid retain cycles, a `strong` `IBOutlet` will also work. – jscs May 04 '12 at 17:31
4

No, IBOutlet is basically stripped when the code is compiled. It is however a helper for XCode so that it can know WHAT is an InterfaceBuilderOutlet.

Basically this word will let you connect the element in the Interface Builder.

By default it will still be strong (just imagine that word isn't there).

However it is suggested that you set it to weak because once something is connected to the interface builder, THAT interface will keep a strong reference to it, so there is no point at having a double strong reference, specially if that element is not meant to be kept alive when the interface has been unloaded.

Read this question which is exactly what you are looking for:

Should IBOutlets be strong or weak under ARC?

Community
  • 1
  • 1
Pochi
  • 13,391
  • 3
  • 64
  • 104
  • 1
    Do I have to declare my IBOutlet as a property? – 0xSina Apr 25 '12 at 03:21
  • No you dont, you can just declare them as instance variables, theres a difference if you do it on MacOS tho, you can read more about it here: http://stackoverflow.com/questions/1221516/does-an-iboutlet-needs-to-be-a-property-synthesized – Pochi Apr 25 '12 at 03:27
  • 1
    ok and if i do declare them as instance variable, best would be like this: __weak IBOutlet UIButton *button, right? – 0xSina Apr 25 '12 at 03:30
  • I think you are going trough a lot of trouble "__weak IBOutlet UIButton *button;" is correct, If you are using arc and xcode 4.2 you should just open the story board and select the element you want to make a reference to. then on the upper right part click on the middle button of the editor (the assistant editor). Then just control drag the button to the header file of the respective viewcontroller, weather you add it as strong or weak xcode will take care of the rest. (make sure the assistance editor is set on automatic and the correct header is selected) – Pochi Apr 25 '12 at 03:36
3

The IBOutlet keyword is only used to associate the object with an element in Interface Builder. It has nothing to do with weak or strong or ARC or memory management.

bbarnhart
  • 6,620
  • 1
  • 40
  • 60
  • That's absurd; the memory management of `IBOutlets` needs to be considered just as does the management of any other variable. – jscs Apr 25 '12 at 03:17
  • 2
    @JacquesCousteau not really, read his answer carefully, the IBOutlet KEYWORD, has nothing to do with weather the property will be set as strong or as weak. what he said is 100% accurate. Regardless of how you decide to manage that objects memory. – Pochi Apr 25 '12 at 03:23
  • A property with IBOutlet would need to be managed as you would manage any other property, but IBOutlet does not factor into it. – bbarnhart Apr 25 '12 at 03:25
  • Okay, syntactically, the presence of the word `IBOutlet` doesn't have an effect on ARC's behavior, but _semantically_ it has a huge effect. – jscs Apr 25 '12 at 03:25
  • That's not true; `IBOutlets` to other than top-level objects should be weak: http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/LoadingResources/CocoaNibs/CocoaNibs.html#//apple_ref/doc/uid/10000051i-CH4-SW6, whereas properties and variables generally should be strong. – jscs Apr 25 '12 at 03:28
  • It is a good practice to set them as weak, but you might as well declare everything strong as long as you nil it in that viewcontrollers view will unload method. I have seen many books which do so, and xcode will do it for you as well. Still there is nothing wrong with this answer. – Pochi Apr 25 '12 at 03:31
  • 3
    @JacquesCousteau that doesn't change the fact that the keyword itself does not imply or effect any particular memory mgmt strategy, which is the whole point of this question and the answer. This answer is correct for this question. – Firoze Lafeer Apr 25 '12 at 03:32
  • @LuisOscar why do I have to set strong properties as nil in unload? I thought that was taken care of by compiler? Or does this just only apply to IBOutlets? – 0xSina Apr 25 '12 at 03:42
  • 1
    @0xSina because when you set a property as strong its reference counting number is increased by 1, if you dont when the view disapears the pointer will be lost but the object will retain the +1 count, hence you get a memory leak. – Pochi Apr 25 '12 at 03:45
  • @LuisOscar ok but in a typical NSObject subclass, I declare I property as strong and that's it. I never had to set it to nil in dealloc (never even overrode dealloc). What's the difference here? Or am I completely confused? – 0xSina Apr 25 '12 at 03:53
  • 1
    @0xSina im afraid that if i keep trying to explain this to you here on the comments you will get more confused. Read part 1 and 2 of this article: http://www.raywenderlich.com/5677/beginning-arc-in-ios-5-part-1 it should make it very clear. – Pochi Apr 25 '12 at 03:59