guide basics swift reference garbage-collection swift2 strong-references

guide - swift ios basics



¿Cómo se pueden identificar ciclos de referencia fuertes en Swift? (5)

¿Existe alguna herramienta o método para localizar ciclos de referencias fuertes en mi código SWIFT?

Un ciclo de referencia fuerte es cuando dos instancias de clases se hacen referencia entre sí sin las medidas de seguridad adecuadas ( weak / unowned ), lo que evita que el recolector de basura las elimine una vez que todas las variables que creé dejaron de hacer referencia a esos objetos.


El método para encontrar ciclos de referencia fuertes es el mismo en Swift que en Objective-C.

Ejecutaría la aplicación desde Xcode, la ejercitaría lo suficiente como para manifestar el ciclo y luego pulsaría el botón "gráfico de memoria de depuración" ( ). Luego, puede seleccionar un objeto inédito en el panel de la izquierda y le mostrará el gráfico de la memoria, que a menudo puede realizar ciclos de referencia claramente fuertes:

A veces, los ciclos de memoria no son tan obvios como eso, pero al menos puede ver qué objeto mantiene una referencia fuerte al objeto en cuestión. Si es necesario, puede seguir hacia atrás e identificar qué mantiene una referencia sólida a eso, y así sucesivamente.

A veces, saber qué tipo de objeto es mantener la referencia fuerte es insuficiente, y realmente desea saber en qué parte de su código se estableció esa referencia fuerte. La opción "malloc stack", como se muestra en https://.com/a/30993476/1271826 , se puede usar para identificar qué era la pila de llamadas cuando se estableció esta fuerte referencia (a menudo le permite identificar la línea de código precisa) donde se establecieron estas fuertes referencias). Para obtener más información, vea WWDC 2016 video Visual Debugging with Xcode .

También puede utilizar instrumentos para identificar objetos filtrados. Simplemente ejecute la aplicación a través de Instrumentos con la herramienta Asignaciones, repetidamente (no solo una o dos veces) devolviendo la aplicación a alguna condición de estado estable y si la memoria continúa aumentando, entonces es probable que tenga un ciclo de referencia sólido. Puede usar la herramienta Asignaciones para identificar qué tipo de objetos no se están liberando, usar la función de "conteo de referencias de registros" para identificar con precisión dónde se establecieron estas fuertes referencias, etc.

Consulte los problemas de la memoria de la solución de video de la WWDC 2013 y el rendimiento de la aplicación de iOS de la WWDC 2012 video : Memoria para conocer las introducciones para identificar y resolver los problemas de memoria. Las técnicas básicas propuestas siguen siendo aplicables hoy (aunque la IU de las herramientas de Instrumentos ha cambiado un poco ... si desea una introducción a la IU ligeramente modificada, vea el video de la WWDC 2014 Mejorando su aplicación con instrumentos ).

Como punto de partida, "recolección de basura" se refiere a un sistema de memoria muy diferente y no es aplicable aquí.


Puede agregar funciones deinit a sus clases que serán llamadas cuando sus objetos sean desasignados.

Si no se está ejecutando la llamada a deinit, mientras se ejecuta la aplicación, puede presionar el botón Debug Memory Graph (encerrado en un círculo a continuación) e inspeccionar qué tiene una referencia a qué.

Use los menús desplegables en la parte superior del panel central para alternar entre clases e instancias de clases.

Si algo se asigna una y otra vez sin ser liberado, debería ver varias instancias, y debería poder ver a través del gráfico direccional si uno de sus hijos tiene una referencia fuerte a su padre.


Puedes usar instrumentos para hacer eso. Como dice el último párrafo de este artículo :

Una vez que se abra Instruments, debe iniciar su aplicación y realizar algunas interacciones, especialmente en las áreas o los controladores de vista que desea probar. Cualquier fuga detectada aparecerá como una línea roja en la sección "Fugas". La vista del asistente incluye un área donde los instrumentos le mostrarán el seguimiento de la pila involucrado en la fuga, brindándole información sobre dónde podría estar el problema e incluso permitiéndole navegar directamente al código ofensivo.


Un enfoque muy simple es poner una impresión en desinicializador.

deinit { print("<yourviewcontroller> destroyed.") }

asegúrese de que está viendo esta línea impresa en la consola. Poner deinit en todos tus controladores de vista. en caso de que no haya podido ver el controlador de vista en particular, significa que se trata de un ciclo de referencia. Las posibles causas son que el delegado sea fuerte, los cierres que capturan el yo, los temporizadores no están desvalidos, etc.


Use instrumentos para verificar si hay fugas y pérdida de memoria. Use Mark Generation (Heapshot) en el instrumento de Asignaciones en instrumentos.

Para saber cómo usar Heapshot para encontrar creap de memoria, consulte: bbum blog

Básicamente, el método es ejecutar la herramienta de asignación de instrumentos, tomar una foto de pila, ejecutar una iteración de su código y tomar otra foto de pila 3 o 4 veces. Esto indicará la memoria asignada y no liberada durante las iteraciones.

Para averiguar los resultados revele para ver las asignaciones individuales.

Si necesita ver dónde se producen retenciones, lanzamientos y autoreleases para los instrumentos de uso de un objeto:

Ejecute en instrumentos, en Asignaciones, active "Recuentos de referencias de grabación" en (Para Xcode 5 y más bajo, debe detener la grabación para configurar la opción). Haga que la aplicación se ejecute, detenga la grabación, profundice y podrá ver dónde se produjeron todas las retenciones, lanzamientos y autoreleases.