What is the difference between Wick references and Anound references?
sobes.tech AI
Answer from AI
Wick reference (weak) — is a non-owning reference. It does not increase the reference count of the object. It is used to prevent strong reference cycles, for example, between a delegate and its owner. If the object pointed to by a weak reference is deallocated, the weak reference automatically becomes nil.
Unowned reference (unowned) — is also a non-owning reference and does not increase the reference count of the object. The difference from weak is that unowned cannot be an optional and must always point to an existing object. If the object pointed to by an unowned reference is deallocated before the reference is accessed, attempting to access this reference will result in a runtime error (fatal error). It is used where the lifecycle of the related object is guaranteed to be longer or equal to the lifecycle of the object with the unowned reference (for example, in a strong reference cycle where one object has a clearly defined lifecycle).
Comparison:
| Feature | weak |
unowned |
|---|---|---|
| Non-owning | Yes | Yes |
| Increases SC | No | No |
| Can be nil | Yes (automatically nilled) | No (must point to an object) |
| Safety | Safer in case of deallocation | Less safe (fatal error on access to deallocated object) |
| Type | Must be optional | Cannot be optional (by default) |
| Usage | Preventing strong reference cycles where the object may cease to exist earlier | Preventing strong reference cycles where the object is guaranteed to exist |
Example of using weak to prevent a strong reference cycle:
class Person {
let name: String
weak var apartment: Apartment? // weak reference to avoid retain cycle
init(name: String) {
self.name = name
print("\(name) is being initialized")
}
deinit {
print("\(name) is being deinitialized")
}
}
class Apartment {
let unit: String
var occupant: Person?
init(unit: String) {
self.unit = unit
print("Apartment \(unit) is being initialized")
}
deinit {
print("Apartment \(unit) is being deinitialized")
}
}
Example of using unowned in the context of capturing self in a closure:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in // unowned self to avoid retain cycle with closure
if let text = self.text {
return "<\(self.name)>\(text)</\(self.name)>"
} else {
return "<\(self.name) />"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) is being deinitialized")
}
}