Unowned Properties in Swift

Unowned Properties in Swift

It's very common to use the weak keyword in order to prevent reference cycles in properties like delegates:

weak var delegate: HomeViewDelegate?

Unfortunately, since it protects you from references being lost, the weak keyword forces the usage of var and an optional type, which can be quite jarring if you're building something like an UIView that is not supposed to be used without a delegate - much less change delegates suddenly:

class HomeView: UIView {
    weak var delegate: HomeViewDelegate?

    func renderView() {
        guard let delegate = delegate else {
            //Timmy: this should never happen!
            return
        }
        let category = delegate.currentlySelectedCategory()
        categoryView.render(category: category)
        delegate.homeViewDidUpdate()
    }
}

But weak is not the only way of breaking reference cycles. Just like in capture lists, the unowned keyword can be used in properties to create non-strong references:

unowned let delegate: HomeViewModelDelegate

Unlike weak, unowned references are expected to always have a value. This allows you to not only use non-optional types when declaring them, but also to do so with let, bringing back immutability and making sure your objects won't act in unexpected ways:

class HomeView: UIView {
    private unowned let delegate: HomeViewDelegate

    init(delegate: HomeViewDelegate) {
        self.delegate = delegate
        super.init(frame: .zero)
    }

    func renderView() {
        let category = delegate.currentlySelectedCategory()
        categoryView.render(category: category)
        delegate.homeViewDidUpdate()
    }
}

With weak, there's nothing stopping HomeView from being used without a delegate, and a guard is required to unwrap values retrieved from the delegate due to the optional requirement of the keyword. On the other hand, unowned allows you to break reference cycles while still using the reference just like if it was strong.

However, be aware that unowned properties will work just like the capture list keyword. If you try to access an unowned reference that has already deallocated, your app will crash.

If your object is guaranteed to never outlive its unowned reference (like a ViewModel, for example), usage of unowned can greatly improve both code quality and performance.

But unowned can crash your app just like implicitly unwrapped optionals. Shouldn't you use weak for everything?

Most people rely on weak for everything and frown upon unowned due to its potential crashes, specially on capture lists. This is a safe way to use Swift, but not Apple's intended practice.

Unlike implicitly unwrapped optionals, which in my opinion are just a lazy way of overcoming architectural problems, unowned references have significant advantages over weak ones: They have better performance, allow immutability, and since they can't be manually set to nil, your code will not accidentally follow unexpected paths. unowned references are perfectly safe - problems will only arise if you misuse the keyword.

According to Apple, you should always use unowned references when your object can't outlive its reference:

Use an unowned reference only when you are sure that the reference always refers to an instance that has not been deallocated.

If you try to access the value of an unowned reference after that instance has been deallocated, you’ll get a runtime error.

If the captured reference will never become nil, it should always be captured as an unowned reference, rather than a weak reference.

In any other cases, you should keep using weak references.

What else?

The next time you create a delegate or an @escaping closure, think about its context and see if it's possible for it to outlive its reference. If it doesn't, you might find unowned properties an interesting tool to improve your code's quality.

Follow me on my Twitter - @rockbruno_, and let me know of any suggestions and corrections you want to share.

References and Good reads

Apple Docs: ARC and Keywords