El principal problema relacionado con la memoria que aún deberá conocer es conservar los ciclos. Esto ocurre cuando un objeto tiene un puntero fuerte a otro, pero el objeto de destino tiene un puntero fuerte de vuelta al original. Incluso cuando se eliminan todas las demás referencias a estos objetos, aún se mantendrán entre sí y no se liberarán. Esto también puede suceder indirectamente, por una cadena de objetos que podrían tener el último en la cadena refiriéndose a un objeto anterior.
Es por esta razón que existen los calificadores de propiedad __unsafe_unretained
y __weak
. El primero no retendrá ningún objeto al que apunte, pero deja abierta la posibilidad de que ese objeto desaparezca y apunte a mala memoria, mientras que el segundo no retiene el objeto y se establece automáticamente en cero cuando su objetivo se desasigna. De los dos, __weak
generalmente se prefiere en plataformas que lo admiten.
Usaría estos calificadores para cosas como los delegados, donde no desea que el objeto retenga a su delegado y potencialmente conduzca a un ciclo.
Otro par de preocupaciones importantes relacionadas con la memoria son el manejo de los objetos de Core Foundation y la memoria asignada usando malloc()
tipos como char*
. ARC no gestiona estos tipos, solo objetos Objective-C, por lo que aún tendrá que lidiar con ellos usted mismo. Los tipos de Core Foundation pueden ser particularmente complicados, porque a veces necesitan ser puenteados para que coincidan con los objetos Objective-C, y viceversa. Esto significa que el control debe transferirse de un lado a otro desde ARC cuando se establece un puente entre los tipos de CF y Objective-C. Se han agregado algunas palabras clave relacionadas con este puente, y Mike Ash tiene una excelente descripción de varios casos de puente en su larga redacción ARC .
Además de esto, hay varios otros casos menos frecuentes, pero aún potencialmente problemáticos, que la especificación publicada detalla.
Gran parte del nuevo comportamiento, basado en mantener los objetos siempre que haya un puntero fuerte para ellos, es muy similar a la recolección de basura en la Mac. Sin embargo, los fundamentos técnicos son muy diferentes. En lugar de tener un proceso de recolección de basura que se ejecuta a intervalos regulares para limpiar objetos que ya no se apuntan, este estilo de administración de memoria se basa en las rígidas reglas de retención / liberación que todos debemos obedecer en Objective-C.
ARC simplemente toma las tareas repetitivas de administración de memoria que hemos tenido que hacer durante años y las descarga al compilador para que nunca tenga que preocuparnos por ellas nuevamente. De esta manera, no tiene los problemas de detención o los perfiles de memoria de diente de sierra experimentados en las plataformas de recolección de basura. He experimentado ambos en mis aplicaciones Mac recolectadas de basura, y estoy ansioso por ver cómo se comportan bajo ARC.
Para más información sobre la recolección de basura vs. ARC, vea esta respuesta muy interesante de Chris Lattner en la lista de correo de Objective-C , donde enumera muchas ventajas de ARC sobre la recolección de basura de Objective-C 2.0. Me he encontrado con varios de los problemas de GC que describe.
ARC no lo ayudará con la memoria que no sea ObjC, por ejemplo, si
malloc()
necesita algo, aún lo necesitafree()
.Se puede engañar a ARC
performSelector:
si el compilador no puede descubrir cuál es el selector (el compilador generará una advertencia al respecto).ARC también generará código siguiendo las convenciones de nomenclatura de ObjC, por lo que si combina el código ARC y MRC puede obtener resultados sorprendentes si el código MRC no hace lo que el compilador cree que prometen los nombres.
fuente
Experimenté pérdidas de memoria en mi aplicación debido a los siguientes 4 problemas:
Afortunadamente, me encontré con la siguiente publicación de blog y pude corregirlos: http://www.reigndesign.com/blog/debugging-retain-cycles-in-objective-c-four- probably- culprits/
fuente
ARC tampoco gestionará los tipos de CoreFoundation. Puede 'puentearlos' (usando
CFBridgingRelease()
) pero solo si lo va a usar como un objeto Objective-C / Cocoa. Tenga en cuenta que CFBridgingRelease solo disminuye el conteo de retención de CoreFoundation en 1 y lo mueve al ARC de Objective-C.fuente
Xcode 9 proporciona una gran herramienta para encontrar ese tipo de problemas. Se llama: " Gráfico de memoria de depuración ". Al usarlo, puede encontrar su objeto filtrado por tipo de clase y puede ver claramente quién tiene una fuerte referencia a él, soltándolo desde allí resuelve su problema. También detecta ciclos de memoria.
Ver más información sobre cómo usarlo
fuente