Lazy Property Setup in Swift

A few weeks ago, I was talking with my friend Robert about Swift. He had a problem. He wanted to create a property of a class that is not an optional, but depends on self for its creation.

The issue revolves around initializers in Swift. If a property is not optional, it must be set before the super’s initializer is called. However, in order to refer to self, the super initializer must be called first. It’s a chicken-and-the-egg problem. I need to set my properties before calling super.init(), but in order to set my properties, I need to refer to self, which I can’t do until I’ve already called super.init().

Hmmm.

I’ve come up with a pretty good solution. Consider a UIDynamicAnimator property on a view controller. I need to initialize it with a reference view of self.view, but I’m in the same situation as Robert was. My solution, which came from a talk with Dave Addey at the WWDC labs, was to use a @lazy property that is set to a self-evaluating closure. The closure returns a reference to the initialized dynamic animator, but it since it’s lazy, it isn’t set until the first time it’s referred to.

@lazy var animator: UIDynamicAnimator = {
    let animator = UIDynamicAnimator(referenceView: self.view)
    return animator
}()

The downside, as I can see it, is that @lazy properties must be var and not let, so you lose some Swift-ness there. Still, it’s better than having an optional type.


Posted on July 5, 2014