0
0
Swiftprogramming~5 mins

Weak references to break cycles in Swift

Choose your learning style9 modes available
Introduction

Sometimes two objects keep each other alive by holding strong references. This causes a memory problem called a cycle. Weak references help stop this by not keeping the other object alive.

When two objects refer to each other and you want to avoid memory leaks.
When you have a parent-child relationship and the child should not keep the parent alive.
When you want to allow one object to disappear even if another still points to it.
When managing delegate patterns where the delegate should not be strongly held.
When breaking cycles in closures that capture self.
Syntax
Swift
class SomeClass {
    weak var otherObject: OtherClass?
}

Use the weak keyword before the variable to make it a weak reference.

Weak references must be optional because the referenced object can disappear (become nil).

Examples
The Person class has a weak reference to Apartment to avoid a cycle.
Swift
class Person {
    var name: String
    weak var apartment: Apartment?
    init(name: String) {
        self.name = name
    }
}
The Apartment class has a strong reference to Person.
Swift
class Apartment {
    let unit: String
    var tenant: Person?
    init(unit: String) {
        self.unit = unit
    }
}
Here, john and unit4A refer to each other, but john.apartment is weak, so no cycle occurs.
Swift
let john = Person(name: "John")
let unit4A = Apartment(unit: "4A")
john.apartment = unit4A
unit4A.tenant = john
Sample Program

This program creates a Person and an Apartment that refer to each other. The Person holds a weak reference to the Apartment. When both variables are set to nil, both objects are properly cleaned up because there is no strong cycle.

Swift
class Person {
    let name: String
    weak var apartment: Apartment?
    init(name: String) {
        self.name = name
        print("Person \(name) is created")
    }
    deinit {
        print("Person \(name) is being deinitialized")
    }
}

class Apartment {
    let unit: String
    var tenant: Person?
    init(unit: String) {
        self.unit = unit
        print("Apartment \(unit) is created")
    }
    deinit {
        print("Apartment \(unit) is being deinitialized")
    }
}

var john: Person? = Person(name: "John")
var unit4A: Apartment? = Apartment(unit: "4A")
john!.apartment = unit4A
unit4A!.tenant = john

john = nil
unit4A = nil
OutputSuccess
Important Notes

Weak references do not increase the reference count of the object.

If the referenced object is deallocated, the weak reference automatically becomes nil.

Use unowned references only when you are sure the referenced object will never be nil during the lifetime of the reference.

Summary

Weak references help avoid memory cycles by not keeping objects alive.

They must be optional because the object they point to can disappear.

Use weak references in relationships where one object should not own the other strongly.