Middle
What is the difference between 'weak' and 'unowned' in Swift?
sobes.tech AI
Answer from AI
weak and unowned are used to resolve cyclic references but differ in their behavior and application.
| Property | 'weak' | 'unowned' |
|---|---|---|
| Type | Optional | Non-optional |
| Lifetime | Can become nil |
Guaranteed to have a value |
| Existence guarantee | No | Yes, until the end of Scope |
| Usage | When it is possible that the related object will be deallocated first. | When the related object will be deallocated either simultaneously with or after the current one. |
| Example | Delegate | Parent-Child relationship |
weak:
- Used when one object can exist without a reference to another, or when one of the objects is allowed to be
nil. - Automatically becomes
nilwhen the object it references is deallocated. - Must be declared as an optional type.
class Person {
let name: String
var apartment: Apartment?
init(name: String) { self.name = name }
deinit { print("\(name) is being deinitialized") }
}
class Apartment {
let unit: String
weak var tenant: Person? // cyclic reference solved with weak
init(unit: String) { self.unit = unit }
deinit { print("Apartment \(unit) is being deinitialized") }
}
var john: Person? = Person(name: "John Appleseed")
var unit4A: Apartment? = Apartment(unit: "4A")
john?.apartment = unit4A
unit4A?.tenant = john // No strong reference cycle
john = nil // Person object is deallocated
// unit4A?.tenant is now nil
unit4A = nil // Apartment object is deallocated
unowned:
- Used when one object belongs to another, and both should exist simultaneously or the related object will outlive the current one.
- Guaranteed to always have a value. Accessing it after deallocation will cause a runtime error.
- Declared as a non-optional type.
class Customer {
let name: String
var card: CreditCard?
init(name: String) { self.name = name }
deinit { print("\(name) is being deinitialized") }
}
class CreditCard {
let number: UInt64
unowned let customer: Customer // cyclic reference solved with unowned
init(number: UInt64, customer: Customer) {
self.number = number
self.customer = customer
}
deinit { print("Card #\(number) is being deinitialized") }
}
var john: Customer? = Customer(name: "John Appleseed")
john!.card = CreditCard(number: 1234_5678_9012_3456, customer: john!) // No strong reference cycle
john = nil // Customer and CreditCard objects are deallocated
The choice between weak and unowned depends on whether the related object can become nil during the lifetime of the current object. If yes, use weak. If not, use unowned.