Middle
Как да предотвратим възникването на цикъл на задържане (retain cycle) в iOS?
sobes.tech AI
Отговор от AI
Циклите на задържане се предотвратяват чрез правилната употреба на слаби (weak) или безусловни (unowned) референции.
Слаби референции (weak):
- Не увеличават брояча на референциите на обекта.
- Могат да станат
nil(nullable). - Използват се, когато един обект може да съществува независимо от друг (например, делегат).
class DelegateExample {
weak var delegate: SomeDelegateType? // Слаба референция към делегата
}
Безусловни unowned референции (unowned):
- Не увеличават брояча на референциите на обекта.
- Са гарантирано ненулеви (
non-nil). - Използват се, когато един обект явно притежава друг, но зависимият обект може да съществува само заедно с притежателя (например, затваряния, които захващат
selfв клас, където затварянето "принадлежи" явно на инстанцията на класа). Достъпът доunownedреференция, когато обектът вече е освободен, ще доведе до грешка по време на изпълнение.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Безусловна `unowned` референция към self
// Използване на self
print("Използване на unowned self")
}
}
}
Използване в затваряния:
Затварянията могат да създадат цикли на задържане, ако захващат инстанции на класове чрез силни референции, и тази инстанция съдържа също силна референция към затварянето. За да се избегне това, се използват списъци за захващане (capture lists) в началото на затварянето:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Слаба референция към self
guard let strongSelf = self else {
return "" // Обработка на случая, когато self вече е 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) се освобождава")
}
}
Изборът между weak и unowned зависи от семантиката на отношенията между обектите:
weak: когато референцията може да станеnilпо време на жизнения цикъл на обекта, към който се отнася.unowned: когато обектът, към който се отнася, съществува гарантирано по-дълго или толкова дълго, колкото и обекта, който го отнася, и референцията никога няма да станеnil.