Should Iboutlets Be Strong or Weak Under Arc

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

Sample Image
Sample Image

When should I use Strong vs Weak for IBOutlets (further clarification)

Most outlets for subviews don't need to be strong references because, after all, they're subviews loaded as part of a view hierarchy. As long as the top-level view exists, and as long as you don't go removing the subviews from their parents, the subviews in the view hierarchy will be retained by their parents for the lifetime of the top-level view.

In the days before ARC, some people were happy to rely on the view hierarchy to retain their views for them and so set their outlet properties to assign. Others didn't like the idea that a hiccup in the view hierarchy could leave them with a handful of dangling pointers, and so set their properties to retain. ARC gives us zeroing weak references, so that your outlets will be set to nil if the objects they point to are deallocated, and that makes using weak references for outlets seem a lot safer. On the other hand, if you want to maintain a reference to a view even if the view hierarchy that contains is is deallocated, you should set that reference to strong.

Since your view controller is responsible for the view hierarchy it manages (i.e. "owns"), it should have a strong reference to the top-level view. You don't need to worry too much about this, as the view property of any UIViewController-derived view controller is set to retain (i.e. strong).

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?.

IBOutlets Strong or Weak - Does it Actually Make a Difference to Memory Management? (ARC)

IBOutlets can declared weak because they will be created during XIB parsing and added to the UIView stack...so you don't need a strong reference to the object.

When you declare an IBOutlet weak you ensure that when the main UIView of UIViewcontroller disappear every subview will be deleted without any memory leak.

When should I use the weak or strong qualifier with IBOutlets?

In general: if you are making an outlet to a subview of the ViewControllers subview it should be weak. The object exists as long as the top view exists (between viewDidLoad and viewDidUnload). As iOS 5 ARC automatically nullifies weak links, when the viewController unloads its view and view hierarchy is destroyed, your outlet is automatically set to nil.

But maybe you want to create another object in your nib file (a model object). As this object is not under the view hierarchy, you need to make the iboutlet strong. If you make it weak linked, the object will be autoreleased since no other object has a strong reference to it and ARC will release it and set nil to your IBOutlet. This is not the case of a subview since its superview mantains a strong link with it.

IBOutlets strong or weak

Instance variables under ARC are strong by default. And they are neither atomic nor nonatomic, since they are just instance variables and not accessor methods. The atomic/nonatomic flags are related to multi threading. They specify whether or not the accessor methods should be atomic. When an accessor is atomic, the execution can't change to an other thread in the middle of the accessor method. When it's nonatomic, there is no such restriction.

Note: IBOutlet is a typedef of nothing. It's just a flag for Interface Builder and has no memory related functions.



Related Topics



Leave a reply



Submit