I\'m making another attempt today to try to understand retain cycles and weak references in Swift. Reading through the documentation, I saw the following code example where one
To augment the accepted answer, here is a concrete example which demonstrates the behavior.
Try this is a Playground:
class Person {
let name: String
init(name: String) { self.name = name }
weak var apartment: Apartment?
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
init(unit: String) { self.unit = unit }
weak var tenant: Person? // <---- This var is marked as 'weak'
deinit { print("Apartment \(unit) is being deinitialized") }
}
class Test {
var person: Person
init() {
person = Person(name: "Fred")
let unit2B = Apartment(unit: "2B")
person.apartment = unit2B
unit2B.tenant = person
print(person.apartment!.unit)
}
func test() {
print(person.apartment!.unit)
}
}
func go() {
let t = Test()
t.test() // crashes here!
}
go()
At the time of init
in class Test
, the apartment that has been created is retained by the local variable unit2B
. When init
is finished, the apartment will be deallocated because there are no longer any strong references holding it, so the program crashes when test
is called because person.apartment
is now nil
.
If you remove the weak
from weak var apartment
in class Person
, then this example won't crash because the apartment created in init
is retained by the person
who is retained by the class property person
.
The other way to fix the example is to make unit2B
be a property of class Test
. Then the apartment would have a strong reference holding it so unit2B
wouldn't be deallocated after init
.
If you remove weak
from both weak var apartment
in class Person
and from weak var tenant
in class Apartment
, then the example won't crash, but neither the Person
nor the Apartment
will be deallocated because of the retain cycle created by two objects holding strong references to each other.