Middle
¿Cómo se puede prevenir la creación de un ciclo de retención (retain cycle) en iOS?
sobes.tech AI
Respuesta de la IA
Los ciclos de retención se previenen mediante el uso correcto de referencias débiles (weak) o no retenedoras incondicionales (unowned).
Referencias débiles (weak):
- No aumentan el contador de referencias del objeto.
- Son nulas (pueden volverse
nil). - Se usan cuando un objeto puede existir independientemente de otro (por ejemplo, un delegado).
class DelegateExample {
weak var delegate: SomeDelegateType? // Referencia débil al delegado
}
Referencias no retenedoras incondicionales (unowned):
- No aumentan el contador de referencias del objeto.
- Garantizadas no nulas.
- Se usan cuando un objeto posee explícitamente a otro, pero el objeto dependiente solo puede existir junto con el propietario (por ejemplo, cierres que capturan
selfen una clase, donde el cierre "pertenece" explícitamente a la instancia de la clase). Acceder a una referenciaunownedcuando el objeto ya ha sido liberado causará un error en tiempo de ejecución.
class Owner {
var closure: (() -> Void)?
func setupClosure() {
closure = { [unowned self] in // Referencia no retenedora incondicional a self
// Uso de self
print("Usando self no retenedor")
}
}
}
Uso en cierres:
Los cierres pueden crear ciclos de retención si capturan instancias de clases mediante referencias fuertes, y esa instancia de clase también contiene una referencia fuerte al cierre. Para evitarlo, se usan listas de captura (capture lists) al inicio del cierre:
class HTMLElement {
let name: String
let text: String?
lazy var asHTML: () -> String = { [weak self] in // Referencia débil a self
guard let strongSelf = self else {
return "" // Manejo del caso cuando self ya es 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á siendo destruido")
}
}
La elección entre weak y unowned depende de la semántica de las relaciones entre objetos:
weak: cuando la referencia puede volversenildurante el ciclo de vida del objeto al que se refiere.unowned: cuando el objeto referenciado existe garantizado por más tiempo o igual que el objeto que lo referencia, y la referencia nunca seránil.