Middle
Cum se poate preveni crearea unui ciclu de retenție (retain cycle) în iOS?
sobes.tech AI
Răspuns de la AI
Ciclurile de retenție sunt prevenite prin utilizarea corectă a referințelor slabe (weak) sau necondiționate (unowned).
Referințe slabe (weak):
- Nu cresc numărătorul de referințe al obiectului.
- Pot deveni
nil(sunt nullable). - Sunt utilizate atunci când un obiect poate exista independent de altul (de exemplu, un delegat).
class DelegateExample {
weak var delegate: SomeDelegateType? // Referință slabă către delegat
}
Referințe necondiționate (unowned):
- Nu cresc numărătorul de referințe al obiectului.
- Sunt garantat non-nule (
non-nil). - Sunt utilizate atunci când un obiect deține explicit altul, dar obiectul dependent poate exista doar împreună cu proprietarul (de exemplu, closures care capturează
selfîntr-o clasă, unde closure-ul "aparține" explicit instanței clasei). Accesarea unei referințeunownedcând obiectul a fost deja eliberat va cauza o eroare la runtime.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Referință necondiționată `unowned` către self
// Utilizarea lui self
print("Utilizare `unowned` self")
}
}
}
Utilizare în closures:
Closures pot crea cicluri de retenție dacă capturează instanțe de clase prin referințe puternice, iar acea instanță de clasă conține și o referință puternică către closure. Pentru a evita acest lucru, se folosesc liste de captură (capture lists) la începutul closure-ului:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Referință slabă către self
guard let strongSelf = self else {
return "" // Tratarea cazului în care self este deja 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) este fiind deinitializat")
}
}
Alegerea între weak și unowned depinde de semantica relațiilor dintre obiecte:
weak: când referința poate deveninilpe parcursul ciclului de viață al obiectului referit.unowned: când obiectul referit există garantat mai mult sau egal cu cel care îl referă, și referința nu va deveni niciodatănil.