Most iOS Developers I’ve talked to about unowned variables disregard its specific usefulness. Even worse, they just default to weak without a justified reason. I think this is because it’s not commonly used in our day-to-day development. But if you spend some time digging into Swift’s own documentation around the topic and doing your own hands-on tinkering, you’ll quickly notice what makes unowned important and realize the distinction between weak and owned.

What makes unowned important is that unlike weak variables, unowned variables can be declared as non-optionals. That means we are responsible for assigning them a value during initialization. Which tells us precisely their usefulness, that we must use unowned when we need to establish a tightly coupled relationship between two objects. For instance, when establishing relationships between a customer and a credit card object, we instinctively know that a customer may or may not own a credit card, but a credit card must always be tied to a customer. If it doesn’t have a customer, well, it’s not a credit card, is it? It’s just a piece of plastic.

Since all weak properties are optional, you can create a credit card without a customer, and this is precisely what you want to avoid. The way to avoid it is by using a non-optional unowned property that enforces the relationship safely.

Here’s an example to demonstrate visually unowned’s usefulness:

Weak:

As you can see, if we use weak, we can initialize a credit card with or without a customer. While this would still work, it’s not explicit and we should aim to be explicit when possible. I assume that is why the Swift creators included unowned in the first place.

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
    let number: UInt64
    weak var customer: Customer?
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)
Unowned:

Here, on the other hand, since we’re using a non-optional unowned, we are required to include the credit card in the initialization. Now by simply looking at this class init method, it’s clear that a credit card must always have a customer, since it’s not possible to create a credit card without one. That’s a level of clarity we can’t achieve if we use a weak variable.

class Customer {
    let name: String
    var card: CreditCard?
    init(name: String) {
        self.name = name
    }
    deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
    let number: UInt64
    unowned var customer: Customer
    init(number: UInt64, customer: Customer) {
        self.number = number
        self.customer = customer
    }
    deinit { print("Card #\(number) is being deinitialized") }
}
var john: Customer?
john = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!)

Here’s a framework I use that helps me remember the functionality of each keyword, and helps me identify in which situations they’re most applicable.

How to make technical concepts easier to recall

Summary

Today we explored the specific difference between unowned and weak. We highlighted the usefulness of using unowned as “clarity” in establishing a reference back to the parent object while avoiding a strong reference cycle, which is the primary purpose of both weak and unowned.

That’s all, my friends. I hope this post unblocks you from any ongoing challenge you may be facing. If you have any questions or edge cases you’d like to discuss, just leave a comment below. If you want to support this blog you can Buy Me a Coffee. You can also connect with me on LinkedIn and Twitter, where I share all my new posts.