Should Iboutlet Be Weak or Strong Var

Should IBOutlets be strong or weak under ARC?

The current recommended best practice from Apple is for IBOutlets to be strong unless weak is specifically needed to avoid a retain cycle. As Johannes mentioned above, this was commented on in the "Implementing UI Designs in Interface Builder" session from WWDC 2015 where an Apple Engineer said:

And the last option I want to point out is the storage type, which can
either be strong or weak. In general you should make your outlet
strong, especially if you are connecting an outlet to a subview or to
a constraint that's not always going to be retained by the view
hierarchy. The only time you really need to make an outlet weak is if
you have a custom view that references something back up the view
hierarchy and in general that's not recommended.

I asked about this on Twitter to an engineer on the IB team and he confirmed that strong should be the default and that the developer docs are being updated.

https://twitter.com/_danielhall/status/620716996326350848
https://twitter.com/_danielhall/status/620717252216623104


weak or strong for IBOutlet and other

A rule of thumb

When a parent has a reference to a child object, you should use a strong reference. When a child has a reference to its parent object, you should use a weak reference or a unsafe_unretained one (if the former is not available). A typical scenario is when you deal with delegates. For example, a UITableViewDelegate doesn't retain a controller class that contains a table view.

Sample Image

Here a simple schema to present the main concepts.

Suppose first A,B and C are strong references. In particular, C has a strong ref to its parent. When obj1 is released (somewhere), the A reference doesn't exist anymore but you have a leak since there is a cycle between obj1 and obj2. Speaking in terms of retain counts (only for explain purposes), obj1 has a retain count of 2 (obj2 has a strong reference to it), while obj2 has a retain count of 1. If obj1 is released, its retain count is now 1 and its dealloc method is not called. obj1 and obj2 still remain in memory but no one has a reference to them: Leak.

On the contary, if only A and B are strong refs and C is qualified as weak all is ok. You have no leaks. In fact, when obj1 is released, it also releases obj2. Speaking in terms of retain counts, obj1 has a retain count of 1, obj2 has a retain count of 1. If obj1 is released, its retain count is now 0 and its dealloc method is called. obj1 and obj2 are removed from memory.

A simple suggestion: Start to think in terms of object graph when you deal with ARC.

About your first question, both solutions are valid when you deal with XIBs. In general weak references are used when you deal with memory cycles.
Concerning XIBs files, if you use strong you need to set nil in viewDidUnload since if you don't do it, in memory low conditions, you could cause unexpected leaks. You don't release them in dealloc because ARC will do it for you.
weak instead doesn't need that treatment since, when the target object is destroyed, those values are set as nil automatically. No dangling pointers anymore.

If you are interested in, I really suggest you to read friday-qa-2012-04-13-nib-memory-management by Mike Ash.

About your second question, if you need to support iOS 4, instead of weak you have to use unsafe_unretained.

Within SO there are a lot of questions/answers. Here the main ones:

How do I replace weak references when using ARC and targeting iOS 4.0?

What kind of leaks does automatic reference counting in Objective-C not prevent or minimize?

using ARC, lifetime qualifier assign and unsafe_unretained

strong / weak / retain / unsafe_unretained / assign

Hope that helps.

Update

As per shaunlim's comment, starting from iOS 6 viewDidUnload method is deprecated. Here I really suggest to see Rob's answer: iOS 6 - viewDidUnload migrate to didReceiveMemoryWarning?.

Swift, two issues. 1) weak var 2) bang operator for @IBOutlet

  1. Swift IBOutlet are weak by default (but others properties are strong by default). So both writing are the same.

You have more details about the difference between weak and strong here


  1. According to apple documentation

When you declare an outlet in Swift, you should make the type of the
outlet an implicitly unwrapped optional (!). This way, you can let the
storyboard connect the outlets at runtime, after initialization.

Does IBOutlet imply __weak?

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.

Why does Xcode create a weak reference for an IBOutlet?

According to iOS Developer Library: link here

Section: Managing the Lifetimes of Objects from Nib Files

From a practical perspective, in iOS and OS X outlets should be
defined as declared properties. 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 therefore typically be weak, because:

Outlets that you create to subviews of a view controller’s view or a
window controller’s window, for example, are arbitrary references
between objects that do not imply ownership.

The strong outlets are
frequently specified by framework classes (for example,
UIViewController’s view outlet, or NSWindowController’s window
outlet).

@property (weak) IBOutlet MyView *viewContainerSubview;

@property (strong) IBOutlet MyOtherClass *topLevelObject;

Swift making IBOutlet as strong

As of Xcode 6 beta 2, Swift does not have a way to designate strong outlets. The workaround is to connect the outlet in IB, then remove the @IBOutlet attribute from your source file.

Update: This has been added in Xcode 6 beta 3.

How IBoutlet hold initial value being weak? Means some other strong object is pointing?

When the scene is loaded from the storyboard the button is added to the view hierarchy before the reference is assigned to the @IBOutlet property. Since the button is in the view hierarchy there is a strong reference to it.

When you say something like

self.buttonOutlet = UIButton() 

The only reference to the new button is a weak property and the compiler warns you that the object will be immediately released.

You can use a local variable to hold a strong reference until the button is added to the view hierarchy.

let newButton = UIButton()
self.view.addSubview(newButton)
self.buttonOutlet = newButton


Related Topics



Leave a reply



Submit