Skip to content
Theory · Memory and ARC · lesson 4 of 7

weak and unowned

In the library, a borrower's card holds a book: while the card is out, the book does not go back to the shelf. But some records hold nothing. The library catalog shows who has a book right now. When the book is returned, the catalog erases that record by itself.

In the previous lesson, the person and the apartment held each other, and both objects leaked. To avoid the cycle, one of the two references has to be such a catalog record: it knows about the object but does not hold it.

SWIFT
class Person {
    var home: Apartment?
    deinit { print("Person freed") }
}
class Apartment {
    weak var tenant: Person?
}

var anna: Person? = Person()
let flat = Apartment()
anna?.home = flat
flat.tenant = anna
anna = nil // Person freed
print(flat.tenant == nil) // true

Let's go through the program:

  1. weak var tenant — the apartment knows its tenant but does not hold them: this reference adds nothing to the count of Person.
  2. After flat.tenant = anna, the person has one strong reference — anna.
  3. anna = nil removes it. The count is zero, deinit runs, and the program prints Person freed.
  4. Swift writes nil into flat.tenant by itself, so print prints true.

There is no cycle any more: the person holds the apartment, and the apartment does not hold the person.

A weak reference

A weak reference is a reference that does not hold its object: it adds nothing to the object's count. When the object is freed, Swift writes nil into it by itself.

How you work with one:

  • you write the word weak before the declaration: weak var tenant: Person?;
  • its type is always optional, because nil has to fit in;
  • you read it like any optional: with if let, ?. or a comparison with nil.

Without ?, the compiler rejects the declaration:

TEXT
error: 'weak' variable should have optional type 'Person?'

That is why a weak reference is safe: if the object is already gone, you read nil.

Which reference to make weak

Of the two references in a cycle, one becomes weak, and the choice is not random. Ask yourself who owns whom:

  • the strong reference goes from the owner to what it owns: the person holds their apartment;
  • the reference back, to the owner, becomes weak: the apartment only knows its tenant.

A parent–child pair works the same way: the parent holds the child with a strong reference, and the child knows its parent through weak. If you do it the other way round, nothing holds the child, and it is freed too early.

An unowned reference

Sometimes an object is sure to live longer than the reference to it. A bank card always has an owner, and the card does not exist without one. For such a reference there is a second kind — an unowned reference. It does not hold the object either, but Swift never writes nil into it, so it is usually declared without ?.

SWIFT
class Customer {
    let name: String
    init(name: String) { self.name = name }
}
class Card {
    unowned let owner: Customer
    init(owner: Customer) { self.owner = owner }
}

var alice: Customer? = Customer(name: "Alice")
let card = Card(owner: alice!)
print(card.owner.name) // Alice

Let's see what happens here:

  1. unowned let owner: Customer — the card knows its owner but does not hold them.
  2. The type has no ?, so card.owner.name is read directly, without if let or ?..
  3. The variable alice holds the owner, and while it does, the card works.

unowned is handier, but riskier. If the owner was freed before the card after all, the reference must not be read:

SWIFT
alice = nil
print(card.owner.name) // ✗

The program crashes: Swift reports that an unowned reference to an object that was already destroyed was read. So unowned is used only when you are sure the object outlives the reference. If in doubt, use weak.

Here the catalog picture ends. weak is like a catalog record that is erased when the book comes back. And unowned is a slip of paper nobody erases: if the book has already been returned, following the slip means crashing the program.

Interviewers like to ask how weak differs from unowned. You can build the answer like this:

  • neither reference holds the object, so both break a cycle;
  • weak is an optional: once the object is freed, it holds nil, and reading it is safe;
  • unowned never turns into nil, and reading it after the object is freed crashes the program;
  • unowned is used only when the object is sure to live longer than the reference.

Common mistake

A new object is put straight into a weak reference:

SWIFT
let studio = Apartment()
studio.tenant = Person() // ✗
print(studio.tenant == nil) // true
TEXT
warning: instance will be immediately deallocated because property 'tenant' is 'weak'

The compiler warns you: the new object has no strong reference at all, and weak does not hold it. The object is freed on the same line — deinit prints Person freed — and tenant becomes nil at once. First put the object into a strong reference, such as let carl = Person(), and only then into studio.tenant.

Key points

  • weak and unowned do not hold the object: they add nothing to its count, so they break a cycle.
  • A weak reference is optional: once the object is freed, Swift writes nil into it.
  • The reference back, to the owner, becomes weak: the child knows its parent through weak, and the parent holds the child with a strong reference.
  • unowned never becomes nil: reading it after the object is freed crashes the program, so it is used only when the object lives longer than the reference.