Middle
Comment prévenir la création d'un cycle de rétention (retain cycle) dans iOS?
sobes.tech IA
Réponse de l'IA
Les cycles de rétention sont évités par une utilisation correcte des références faibles (weak) ou non retenues inconditionnelles (unowned).
Références faibles (weak):
- N'augmentent pas le compteur de références de l'objet.
- Sont nullables (peuvent devenir
nil). - Utilisées lorsque un objet peut exister indépendamment d'un autre (par exemple, un délégué).
class DelegateExample {
weak var delegate: SomeDelegateType? // Référence faible au délégué
}
Références non retenues inconditionnelles (unowned):
- N'augmentent pas le compteur de références de l'objet.
- Garanties non nulles.
- Utilisées lorsque un objet possède explicitement un autre, mais l'objet dépendant ne peut exister qu'avec le propriétaire (par exemple, des closures capturant
selfdans une classe, où la closure "appartient" explicitement à l'instance de la classe). Accéder à une référenceunownedlorsque l'objet a déjà été libéré provoquera une erreur à l'exécution.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Référence non retenue inconditionnelle à self
// Utilisation de self
print("Utilisation de self non retenu")
}
}
}
Utilisation dans les closures:
Les closures peuvent créer des cycles de rétention s'ils capturent des instances de classes par référence forte, et cette instance de classe contient également une référence forte au closure. Pour éviter cela, on utilise des listes de capture (capture lists) au début du closure:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Référence faible à self
guard let strongSelf = self else {
return "" // Gestion du cas où self est déjà 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) est en train d'être désinitialisé")
}
}
Le choix entre weak et unowned dépend de la sémantique des relations entre objets:
weak: lorsque la référence peut devenirnildurant le cycle de vie de l'objet référencé.unowned: lorsque l'objet référencé existe garantis plus longtemps ou aussi longtemps que l'objet qui le référence, et que la référence ne deviendra jamaisnil.