← Back to archive

Development · Swift

Strong, weak, and unowned references in Swift

Compare how strong, weak, and unowned references affect object lifetimes under ARC.

Read the Korean original on Velog ↗English translation

Development archive cover

Two objects can keep each other alive long after they disappear from the screen. Understanding how ARC counts references helps explain how strong, weak, and unowned references change that relationship.

Reference cycles

A cycle occurs when objects refer back to one another, such as A holding B while B holds A. If both references are strong, their reference counts cannot reach zero simply by removing outside references. The objects remain allocated, causing a memory leak.

class ClassA {
    var instanceB: ClassB?
    deinit {
        print("ClassA Deinitialized")
    }
}

class ClassB {
    var instanceA: ClassA?
    deinit {
        print("ClassB Deinitialized")
    }
}

var instanceA: ClassA? = ClassA()
var instanceB: ClassB? = ClassB()

// Reference each other
instanceA?.instanceB = instanceB
instanceB?.instanceA = instanceA

// Outside references are nil, but the strong reference cycle remains
instanceA = nil
instanceB = nil

Strong references

Strong is the default reference type. A strong reference keeps an object alive by contributing to its reference count.

class Person {
    var pet: Pet?
}

class Pet {
    var owner: Person?
}

let snack = Person()
let cream = Pet()

snack.pet = cream
cream.owner = snack

// A strong reference cycle keeps snack and cream alive.

Weak references

A weak reference does not increase the object's reference count. It becomes nil when the object is deallocated, so a weak reference must be optional.

class Person {
    var pet: Pet?
}

class Pet {
    weak var owner: Person?
}

let snack = Person()
let cream = Pet()

snack.pet = cream
cream.owner = snack

// The weak owner reference becomes nil when its target is deallocated.

Unowned references

An unowned reference does not increase the reference count either. Use it when the referenced object is guaranteed to remain alive for as long as the reference is accessed. Unlike a weak reference, it is not automatically set to nil. Accessing it after the object has been deallocated causes a runtime error.

class Person {
    var pet: Pet?
}

class Pet {
    unowned var owner: Person
    init(owner: Person) {
        self.owner = owner
    }
}

let snack = Person()
let cream = Pet(owner: snack)

snack.pet = cream

// Accessing cream.owner after snack is deallocated causes a runtime error.

Further reading: Swift: Automatic Reference Counting.

← Back to archive