ARC (Automatic Reference Counting) — sistema de gestión automática de memoria en Swift. Con cada nueva referencia fuerte a un objeto, el contador se incrementa; al eliminarse, se decrementa. Cuando el contador es cero, el objeto se libera.
Ciclo de retención — situación en la que los objetos se refieren entre sí mediante referencias fuertes y nunca se liberan.
Formas de evitarlo:
protocol SomeDelegate: AnyObject { } class Owner { weak var delegate: SomeDelegate? }
[weak self] o [unowned self]:class Example { var closure: (() -> Void)? func setup() { closure = { [weak self] in self?.doSomething() } } func doSomething() { } }
¿Cuál es la diferencia entre [weak self] y [unowned self] dentro de un closure? ¿Qué tipo de referencias usar y cuándo?
Respuesta:
[weak self] crea una referencia opcional; self puede ser nil, por lo que generalmente se utiliza una extracción segura self?.[unowned self] crea una referencia no opcional y NO incrementa el contador; si el objeto ya ha sido liberado y se intenta acceder a él, habrá un crash.[unowned self].Ejemplo:
someClosure = { [weak self] in self?.doTask() } // o (si self 100% vive más que closure): someClosure = { [unowned self] in doTask() }
Historia
En el proyecto surgió una situación de ciclo de retención entre ViewController y su closure, vinculado al manejo de toques. ViewController hacía referencia a closure, que capturaba self con una referencia fuerte. Como resultado, el controlador y todos sus datos no se liberaban después de cerrar la pantalla. El problema se solucionó incorporando [weak self] en el closure.
Historia
Implementación del patrón delegate entre dos objetos. El delegate se declaró como una propiedad fuerte (
strong). Como resultado, al intentar eliminar el objeto principal de la memoria, no se desasignó, lo que provocó una fuga de memoria. Después de cambiar el delegate a weak, el problema desapareció.
Historia
Para la animación se utilizó un closure dentro de UIView. El closure capturaba self usando
[unowned self]. Cuando se eliminaban las vistas antes de que la animación terminara, la aplicación se bloqueaba debido al acceso a un self ya liberado. La solución fue utilizar[weak self]y una verificación obligatoria para asegurarse de que self no fuera nil dentro del closure.