Middle
Kā novērst noturēšanas ciklu (retain cycle) iOS?
sobes.tech AI
Atbilde no AI
Atsargu izmantojot vājas (weak) vai beznosacījuma (unowned) atsauces, tiek novērsti cikliem noturēšanas.
Vājas atsauces (weak):
- Nepieciešams palielināt atsauces skaitītāju.
- Var kļūt par
nil. - Tiek izmantotas, kad viens objekts var pastāvēt neatkarīgi no otra (piemēram, deleģents).
class DelegateExample {
weak var delegate: SomeDelegateType? // Vāja atsauce uz deleģentu
}
Beznosacījuma (unowned) atsauces:
- Nepieciešams palielināt atsauces skaitītāju.
- Garantēti nav
nil. - Tiek izmantotas, kad viens objekts skaidri pieder citam, bet atkarīgais objekts var pastāvēt tikai kopā ar īpašnieku (piemēram, aizkavi, iekļaujot
selfklasē, kur aizkave skaidri "pieder" klases eksemplāram). Piekļūstotunownedatsaucei, ja objekts jau ir atbrīvots, notiek izpildes kļūda.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Beznosacījuma neuzturīga atsauce uz self
// Izmantošana self
print("Izmantošana beznosacījuma self")
}
}
}
Izmantošana aizkavējumos:
Aizkaves var izraisīt ciklus, ja tās iekļauj klases eksemplārus ar stipru atsauci, un šis klases eksemplārs satur arī stipru atsauci uz aizkavi. Lai to novērstu, tiek izmantotas uzkrāšanas saraksti (capture lists) aizkaves sākumā:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Vāja atsauce uz self
guard let strongSelf = self else {
return "" // Gadījums, kad self jau ir `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) tiek deaktivēts")
}
}
Izvēle starp weak un unowned ir atkarīga no objektu attiecību semantikas:
weak: kad atsauce var kļūt parnildzīves cikla laikā.unowned: kad objekts, uz kuru atsaucas, garantēti pastāv ilgāk vai vienādi ilgi kā objekts, uz kuru tas atsaucas, un atsauce nekad nebūsnil.