What is the difference between strong, weak and unowned references?
TL;DR
- strong (default): keeps the object alive.
- weak: does not keep it alive. It is always optional and becomes
nilwhen the object is freed. - unowned: does not keep it alive. It is not optional. Using it after the object is freed crashes.
Use weak when the other object may disappear first. Use unowned only when it is guaranteed to live at least as long.
Strong
final class Owner {
var dog: Dog? // strong by default
}As long as owner.dog points to the dog, the dog stays in memory. Most references should be strong.
Weak
final class Dog {
weak var owner: Owner? // must be var and optional
}
var owner: Owner? = Owner()
let dog = Dog()
dog.owner = owner
owner = nil
print(dog.owner) // nil, the owner was freedRules:
- Must be an optional type.
- Usually a
var. Since Swift 6.2 you can also writeweak let; it still becomesnilwhen the object is freed. - Only works with class types (and class-bound protocols).
The delegate pattern
protocol ListViewDelegate: AnyObject {
func didSelect(row: Int)
}
final class ListView {
weak var delegate: ListViewDelegate?
}The view controller owns the list view. The list view points back to the controller weakly. No cycle.
AnyObject is required. Without it, the protocol could be adopted by a struct, and weak would not make sense.
Unowned
final class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
}
final class CreditCard {
unowned let customer: Customer // a card never outlives its customer
init(customer: Customer) { self.customer = customer }
}
let ana = Customer(name: "Ana")
ana.card = CreditCard(customer: ana)unowned is not optional. You do not need to unwrap it. But if the customer is freed and the card is still used, the app crashes:
Fatal error: Attempted to read an unowned reference but object was already deallocatedComparison
| strong | weak | unowned | |
|---|---|---|---|
| Keeps object alive | Yes | No | No |
| Optional | Can be either | Always | No (can be unowned var x: T?) |
| When object is freed | — | Becomes nil | Dangling, crash on access |
| Cost | Retain/release | Side table, slightly slower | Cheap |
| Typical use | Ownership | Delegates, parent links, [weak self] | Child that cannot outlive parent |
In closures
final class SearchViewModel {
var results: [String] = []
var onUpdate: (() -> Void)?
func bind() {
onUpdate = { [weak self] in
guard let self else { return }
print(self.results.count)
}
}
}[weak self] is the safe default for stored or long-living closures. [unowned self] is fine only when the closure cannot outlive self, for example a lazy var closure used only by the object itself.
unowned(unsafe)
unowned(unsafe) let parent: NodeNo safety check at all. Using it after the object is freed reads random memory. It exists for rare performance cases. Avoid it in app code.
How to choose
- Does this object own the other one? Use strong.
- Can the other object be freed while this one still exists? Use
weak. - Is the other object guaranteed to outlive this one, and you want no optional?
unowned.
When in doubt, choose weak. A nil is easier to handle than a crash.
Common follow-up questions
- Can you use
weakwith a struct? No. Structs are value types. There is no shared object to point to weakly. - Why are IBOutlets often
weak? The view hierarchy already owns subviews strongly. A weak outlet avoids holding a second strong reference. Strong outlets are also fine today. - Is
weakslower thanunowned? A little. Weak references use a side table and an atomic load. The difference matters only in very hot code. - What happens to a weak reference in a collection?
[weak Foo]is not valid. Wrap it:struct Weak<T: AnyObject> { weak var value: T? }, or useNSHashTable.weakObjects(). - Does
weakfix all retain cycles? It fixes the cycle if you put it on the right link. Use the memory graph debugger to check.