How do you decide between weak, unowned and strong for a back-reference?
Predict first
What does this print?
final class Customer {
var card: Card?
deinit { print("customer gone") }
}
final class Card {
unowned let owner: Customer
init(_ c: Customer) { owner = c }
deinit { print("card gone") }
}
var c: Customer? = Customer()
c!.card = Card(c!)
c = nil
- Nothing, it leaks
- customer gone, card gone
- card gone, customer gone
Mental model. A card cannot outlive the customer it belongs to, so it may point at the customer without worrying. A visitor’s badge may outlive the host, so it needs a way to say “host left”.
Draw the ownership tree: every object has one clear owner that holds it strongly. A reference against that direction (child to parent, delegate to owner, observer to subject) must not be strong, or you create a cycle. Then ask whether the back-reference can ever be used after its target is gone.
If the holder cannot exist without its target by construction, such as a credit card that is always created for one customer and dies with it, use unowned: it is non-optional and documents the invariant. If the two lifetimes are independent, such as a delegate that may be replaced or a parent that can be released first, use weak. When in doubt choose weak: a surprise nil is handled, a surprise unowned read is a crash.
The customer owns the card strongly; the card points back unowned. Releasing the customer runs its deinit, then releases the card.
Common traps
- Choosing unowned because “it should always be there”. Reality is full of teardown orders you did not plan for.
- Weak everywhere. Hiding ownership makes objects vanish unexpectedly. Keep one strong owner.
They might follow up with
- What about a closure capturing
self? The same rule applies; see the capture-list questions in the closures section. - How do you verify the invariant? A unit test that deallocates the owner while the holder is still around, or a
deinitlog.
Related questions
- 3.2.1 What is the difference between strong, weak, unowned and unowned(unsafe)?
- 3.2.5 What happens to an object’s memory while unowned references to it still exist?
- 3.3.1 What is a retain cycle, and how do you find and fix one?
← Why is a weak reference optional, what can be weak, and what is the… What is unowned(unsafe), and when would you ever use it? →