Na czym polega różnica między linkami Wick a linkami Anound?
sobes.tech AI
Odpowiedź od AI
Odwołanie słabe (weak) to odwołanie, które nie zwiększa licznika odwołań obiektu. Używa się go do zapobiegania cyklom silnych odwołań, na przykład między delegatem a jego właścicielem. Jeśli obiekt, na który wskazuje słabe odwołanie, zostanie zwolniony, słabe odwołanie automatycznie stanie się nil.
Odwołanie nieposiadające (unowned) jest również odwołaniem, które nie zwiększa licznika odwołań obiektu. Różni się od weak tym, że unowned nie może być opcjonalne (Optional) i zawsze musi wskazywać na istniejący obiekt. Jeśli obiekt, na który wskazuje unowned, zostanie zwolniony przed końcem życia odwołania, dostęp do tego odwołania spowoduje błąd wykonania (błąd krytyczny). Używa się go tam, gdzie cykl życia powiązanego obiektu jest gwarantowany, że jest dłuższy lub równy cyklowi życia obiektu z odwołaniem unowned (np. w cyklu silnych odwołań, gdzie jeden z obiektów ma jasno określony cykl życia).
Porównanie:
| Cecha | weak |
unowned |
|---|---|---|
| Nieposiadający | Tak | Tak |
| Zwiększa SC | Nie | Nie |
Może być nil |
Tak (automatycznie nullowane) | Nie (musi wskazywać na obiekt) |
| Bezpieczeństwo | Bardziej bezpieczny w przypadku deallokacji | Mniej bezpieczny (błąd krytyczny przy dostępie do zdeallokowanego obiektu) |
| Typ | Musi być opcjonalny | Nie może być opcjonalny (domyślnie) |
| Użycie | Zapobieganie cyklom silnych odwołań, gdy obiekt może przestać istnieć wcześniej | Zapobieganie cyklom silnych odwołań, gdy obiekt gwarantuje istnienie |
Przykład użycia weak do zapobiegania cyklom silnych odwołań:
class Person {
let name: String
weak var apartment: Apartment? // słabe odwołanie, aby uniknąć cyklu
init(name: String) {
self.name = name
print("\(name) został zainicjalizowany")
}
deinit {
print("\(name) został zniszczony")
}
}
class Apartment {
let unit: String
var occupant: Person?
init(unit: String) {
self.unit = unit
print("Mieszkanie \(unit) zostało zainicjalizowane")
}
deinit {
print("Mieszkanie \(unit) zostało zniszczone")
}
}
Przykład użycia unowned w kontekście przechwytywania self w zamknięciu:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = {
[unowned self] in // unowned self, aby uniknąć cyklu w zamknięciu
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) został zniszczony")
}
}