Comprensión durante la lectura
¿Qué es exactamente un "retain cycle" y por qué impide la desasignación de un objeto?
Un ciclo de retención aparece cuando dos objetos tienen referencias fuertes entre ellos. ARC elimina los objetos cuando el contador de cada uno llega a cero, sin embargo, debido que los dos objetos se referencian entre sí, ARC no es capaz de eliminarlos y se produce una fuga de memoria.
¿En qué situaciones concretas puede surgir un "retain cycle" al usar Task?
Aparece un ciclo de retención cuando un objeto retiene al Task y este, a su vez, retiene al objeto directa o indirectamente (a través de una referencia hacia alguna de sus propiedades).
Por otro lado, aunque no es un ciclo de retención estrictamente hablando, cuando el Task tiene una referencia fuerte a un objeto y lo retiene hasta que termina de ejecutar, también puede resultar un comportamiento inesperado.
El problema es especialmente delicado cuando el Task se ejecuta por un tiempo prolongado, como cuando se usa AsyncSequence para monitorear un evento a lo largo del tiempo. En este caso no se puede liberar al objeto retenido por el Task mientras que esté monitoreando, para lo cual se requiere detener manualmente esta actividad para poder liberar la referencia.
¿Cuál es la diferencia entre un "retain cycle" y una "one-way retention"?
En un ciclo de retención, hay dos objetos que tienen referencias fuertes entre sí.
En un "one-way retention", el objeto NO retiene al Task, pero el Task SÍ retiene al objeto y no deja que se libere hasta que haya terminado su trabajo.
¿Cómo y cuándo se puede romper un "retain cycle" manualmente?
El ciclo de retención puede romperse cuando se usa un [weak self] para no crearlo inicialmente, y cuando se cancela explícitamente el Task antes de liberar el objeto.
Aquí es importante no depender del deinit para la cancelación porque, precisamente, si hay un ciclo de retención, nunca se va a llamar el deinit.
¿Qué limitaciones existen en Swift 6.2 respecto a deinit y los actores?
Antes de Swift 6.2, los deinit eran nonisolated y no podían llamar métodos aislados. Ahora, desde Swift 6.2, se pueden modificar el deinit con isolated. Esto permite a un actor ejecutar métodos desde el deinit. Sin embargo, no soluciona el problema del ciclo de retención - Como hay un ciclo de retención, nunca se va a llamar el deinit.
Top comments (0)