Middle
Kaip išvengti retencijos ciklo (retain cycle) iOS?
sobes.tech AI
Atsakymas iš AI
Atsargiai naudojant silpnus (weak) arba be sąlygų (unowned) nuorodų ciklai yra išvengiami.
Silpnos nuorodos (weak):
- Nepadidina objekto nuorodų skaitiklio.
- Gali tapti
nil. - Naudojamos, kai vienas objektas gali egzistuoti nepriklausomai nuo kito (pavyzdžiui, delegatas).
class DelegateExample {
weak var delegate: SomeDelegateType? // Silpna nuoroda į delegatą
}
Be sąlygų (unowned) nuorodos:
- Nepadidina objekto nuorodų skaitiklio.
- Garantuoja, kad nėra
nil. - Naudojamos, kai vienas objektas aiškiai priklauso kitam, bet priklausomas objektas gali egzistuoti tik kartu su savininku (pavyzdžiui, uždarymai, įtvirtinantys
selfklasėje, kur uždarymas aiškiai "priklauso" klasei). Prieš pasiekiantunownednuorodą, jei objektas jau atlaisvintas, įvyksta klaida vykdymo metu.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Be sąlygų nevaldomas nuoroda į self
// Naudojimas self
print("Naudojant unowned self")
}
}
}
Naudojimas uždarymuose:
Uždarymai gali sukelti ciklus, jei jie įtvirtina klasių egzempliorius stiprią nuorodą, ir šis egzempliorius taip pat turi stiprią nuorodą į uždarymą. Norint to išvengti, naudojami įtvirtinimo sąrašai (capture lists) pradžioje:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Silpna nuoroda į self
guard let strongSelf = self else {
return "" // Kai self jau `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) yra išjungtas")
}
}
Pasirinkimas tarp weak ir unowned priklauso nuo santykių semantikos:
weak: kai nuoroda gali taptinilper objekto gyvavimo ciklą.unowned: kai objektas, į kurį nuoroda, garantuotai egzistuoja ilgiau arba tiek pat, kiek objektas, kuris į jį nuoroda, ir nuoroda niekada nebusnil.