Chris Dzombak

sharing preview • dzombak.com

IBOutlet declarations in Swift

Xcode’s default IBOutlet declarations are weak references to implicitly unwrapped optionals. This is wrong.

IBOutlet declarations in Swift

Update, March 28, 2016: I now believe this more nuanced discussion is more useful. You should go read that post instead. It puts forth three rules for determining whether to use ! or ?, and weak or strong, on IBOutlets:

  1. ! needs a guarantee that the view exists, so always use strong to provide that guarantee
  2. If it’s possible the view isn’t part of the view hierarchy, use ? and appropriate optional-handling (optional binding/chaining) for safety
  3. If you don’t need a view anymore after removing it from the view hierarchy, use weak so it gets removed from memory.

This post remains online for historical reference.

Xcode 6.3 beta adds IBOutlet declarations like this by default:

@IBOutlet weak var activityIndicator: UIActivityIndicatorView!

I argue that this is wrong and unsafe. Making a weak optional implicitly unwrapped (!) is risky at best; weak specifically means that this variable could, in principle, become nil at any time, and combining it with ! seems to me like a recipe for disaster.

A fellow developer asked me yesterday, “the whole reason for declaring as weak is that there at least one reference to the view (indirectly) via the view controller’s view hierarchy. Doesn’t that make you feel any better?”

It doesn’t.

I’d argue that the reason for declaring these references weak is actually that when the view hierarchy goes away we don’t need them; and declaring them weak means we don’t end up with references to dangling views which are no longer necessary.

The reason we can declare them weak is that the views are retained, indirectly, via the view hierarchy. But that’s mostly a detail separate from our intent—our why in declaring the references as weak.

That’s a stupidly pedantic point on my part, but I think it is helpful here to clarify why we’ve done this vs. the reason we can do it.

When I write the reasoning out like this, it’s clear (to me) that the reason view references are weak is because their lifecycles aren’t intimately tied to the view controller.

We must decide whether we’re interested in the lifecycle of this object.

By declaring weak we’re explicitly saying “we aren’t tied to the lifecycle of this view, and if it goes away we don’t want to prevent that”.

But ! runs counter to that statement: it says implicitly “we expect this to practically always to be present, it’s just not set in init”.

This is what makes this sort of declaration such a conflict in my mind: either we care (!) or we don’t (weak) about this object’s lifecycle.

(And in this particular case, I’m willing to bet there’s some pathological case, perhaps while the view is being destroyed, when this reference could be nil but the view controller is still around. And if a notification or KVO event comes in at just the right time, and we try to update activityIndicator based on that event, the whole app blows up trying to unwrap the optional.)