Middle
Jak zabránit vzniku cyklu udržení (retain cycle) v iOS?
sobes.tech AI
Odpověď od AI
Cyklusy udržení jsou předcházeny správným použitím slabých (weak) nebo nepodmíněných (unowned) odkazů.
Slabé odkazy (weak):
- nezvyšují počítadlo odkazů objektu.
- mohou být
nil(nullable). - používají se, když objekt může existovat nezávisle na jiném (například delegát).
class DelegateExample {
weak var delegate: SomeDelegateType? // Slabý odkaz na delegáta
}
Nepodmíněné unowned odkazy (unowned):
- nezvyšují počítadlo odkazů objektu.
- jsou garantovaně nenulové (
non-nil). - používají se, když jeden objekt výslovně vlastní jiný, ale závislý objekt může existovat pouze spolu s vlastníkem (například, uzávěry, které zachycují
selfve třídě, kde uzávěr "patří" výslovně instanci třídy). Přístup kunownedodkazu, když je objekt již uvolněn, způsobí runtime chybu.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Nepodmíněný `unowned` odkaz na self
// Použití self
print("Použití unowned self")
}
}
}
Použití v uzávěrech:
Uzávěry mohou vytvářet cykly udržení, pokud zachycují instance tříd silnými odkazy, a tato instance třídy také obsahuje silnou odkaz na uzávěr. Aby se tomu zabránilo, používají se seznamy zachycení (capture lists) na začátku uzávěru:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Slabý odkaz na self
guard let strongSelf = self else {
return "" // Ošetření případu, kdy je self již 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) je uvolněn")
}
}
Volba mezi weak a unowned závisí na sémantice vztahů mezi objekty:
weak: když odkaz může během životního cyklu objektu, na který odkazuje, býtnil.unowned: když referencovaný objekt existuje garantovaně déle nebo stejně dlouho jako objekt, který na něj odkazuje, a odkaz nikdy nebudenil.