Middle
Jak można zapobiec powstaniu cyklu zatrzymania (retain cycle) w iOS?
sobes.tech AI
Odpowiedź od AI
Cyklów utrzymania (retencji) można zapobiec, stosując poprawne użycie słabych (weak) lub nieutrzymujących (unowned) referencji.
Słabe referencje (weak):
- Nie zwiększają licznika referencji obiektu.
- Mogą stać się
nil(są nullable). - Używa się ich, gdy obiekt może istnieć niezależnie od innego (np. delegat).
class DelegateExample {
weak var delegate: SomeDelegateType? // Słaba referencja do delegata
}
Nieutrzymujące referencje incondycyjne (unowned):
- Nie zwiększają licznika referencji obiektu.
- Są gwarantowanie niepuste (
non-nil). - Używa się ich, gdy jeden obiekt wyraźnie posiada inny, ale obiekt zależny może istnieć tylko razem z właścicielem (np. zamknięcia, które przechwytują
selfw klasie, gdzie zamknięcie "należy" wyraźnie do instancji klasy). Dostęp dounownedspowoduje błąd w czasie wykonywania, jeśli obiekt został już zwolniony.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Nieutrzymująca referencja incondycyjna do self
// Użycie self
print("Używanie unowned self")
}
}
}
Użycie w zamknięciach:
Zamknięcia mogą tworzyć cykle utrzymania, jeśli przechwytują instancje klas przez silne referencje, a ta instancja zawiera również silną referencję do zamknięcia. Aby tego uniknąć, używa się list przechwytywania (capture lists) na początku zamknięcia:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Słaba referencja do self
guard let strongSelf = self else {
return "" // Obsługa przypadku, gdy self jest już nil
}
if let text = strongSelf.text {
return "<\(strongSelf.name)>\(text)</\(strongSelf.name)>"
} else {
return "<\(strongSelf.name)/>"
}
}
init(name: String, text: String? = nil) {
self.name = name
self.text = text
}
deinit {
print("\(name) jest wywoływany")
}
}
Wybór między weak a unowned zależy od semantyki relacji między obiektami:
weak: gdy referencja może stać sięnilw trakcie cyklu życia obiektu, na który się odwołuje.unowned: gdy obiekt, na który się odwołuje, istnieje gwarantowanie dłużej lub tak długo jak obiekt, który go odwołuje, i referencja nigdy nie stanie sięnil.