Desarrollo iOS: Introducción a Automatic Reference Counting (ARC)

Ahorrate muchos problemas simplificando la gestión de memoria en tus aplicaciones.

Quizás uno de los cambios más abrumadores de iOS ha sido la inclusión de ARC (Automatic Reference Counting), lo cual facilita al desarrollador la gestión de memoria, uno de los puntos mas conflictivos del desarrollo iOS.

Por entender la diferencia, hasta iOS 4, el programador debía hacerse cargo de hacer el RELEASE de las variables que ya no fuera a utilizar, y de los RETAIN de aquellas que quiera que se conserven. Concretamente cuando un objeto se esta utilizando desde varios sitios, se produce lo que se llama Reference Counting, que no es mas que un contador de los sitios donde se esta utilizando dicho objeto. De este modo, cuando las diferentes partes de nuestra aplicación van liberando este objeto mediante su método RELEASE, el contador va disminuyendo, y al llegar a cero, se destruye automáticamente liberando ese espacio en memoria.

¿Y que ocurría si por cualquier motivo no estuviéramos realizando correctamente los RELEASE de dicho objeto? Pues bien, que al no llegar dicho contador a cero, la memorial consumida por el objeto nunca se liberaba.

Quizás esta problemática de la memoria, en una aplicación pequeña y sin gran cargas de proceso, pueda parece una finura innecesaria. Sin embargo, en aplicaciones donde la carga de memoria sea superior, es básico realizar una buena gestión de la memoria.

Ahora con iOS 5, llega ARC, que hace todo este trabajo por nosotros de forma automática, garantizando así las buenas prácticas en lo que a memoria se refiere. ARC es una funcionalidad proporcionada por LLVM 3.0, que es el nuevo compilador incorporado por Apple como predeterminado en Xcode 4.2.

ARC realizará por nosotros todas las operativas de RETAIN y RELEASE sin que tengamos que preocuparnos por ello.

La regla es realmente sencilla, ya no tenemos que hacer RETAIN de los objetos, sino que simplemente al establecer un puntero a un objeto, este implicara que el objeto se conserve.  En el momento que liberemos dicho puntero, el objeto se liberará automáticamente si no existen otros punteros al mismo.

Un concepto que deberemos tener siempre en mente es el tipo de relación que queremos establecer entre el puntero y los objetos a los que apunta. Ésta podrá ser de dos tipos dependiendo de su naturaleza:

  • Strong: un puntero de este tipo, implica que nuestra variable será la dueña del objeto al que apunta el puntero, y por tanto no se liberará el mismo mientras el puntero sigua activo.
  • Weak: es un puntero que no implica que nuestra variable sea dueña del objeto apuntado. De este modo, si por cualquier motivo el objeto apuntado fuera liberado, nuestro puntero pasaría ser automáticamente NIL (esto evita que se produzcan errores por apuntar a direcciones de memoria inexistentes).

Para establecer que un objeto tiene un puntero de estos tipos, se puede utilizar el prefijo __weak y __strong al declarar los mismos, de la siguiente manera:

1
__strong NSString *nombre = self.cajaTexto.text;

Dado que las variables por defecto son de tipo STRONG, este código realmente no tiene mucho sentido.

Tambien podemos definir el tipo de relación en la creación de properties dentro de nuestras clases:

1
@property (nonatomic, strong) NSString *nombre;

El hecho de que al eliminar un objeto que tuviera un puntero de tipo WEAK apuntándole este puntero pase automáticamente a ser NIL es un gran ventaja, que permite implementar códigos que antes eran realmente imposibles al producir errores de ejecución.

ARC tiene también algunas limitaciones que es necesario conocer:

  • Sólo es posible utilizar ARC en Objective-C. En caso de utilizar Core Foundation  o sentencias como MALLOC o FREE, deberemos ser nosotros los que nos encarguemos de la gestión de memoria.
  • Aunque ARC hace mucho del trabajo de gestión de memoria por nosotros, no debemos pensar que podemos olvidarnos por completo de dicha gestión. Si tenemos punteros que ya no estamos utilizando, y olvidamos cambiar el valor de los mismos a NIL, éstos permanecerán en memoria ocasionando los mismos problemas de recursos que teníamos antes de ARC.

Ahora mismo la utilización de ARC es algo opcional que puede configurarse en la creación de un proyecto X-Code. Sin embargo, parece que esta forma de trabajar va a ser la predeterminada en el futuro y por tanto es bueno que nos vayamos acostumbrando a su uso.

Si tenemos un proyecto realizado sin ARC, y queremos migrarlos a esta nueva estrategia, Apple nos provee de un sencillo asistente que hace todos los cambios por nosotros mismos. Este asistente se encuentra en el menú “Edit / Refactor / Convert to Objective-C ARC”.

Dependerá del volumen e implementación de vuestro código que este proceso sea mas o menos sencillo. En aplicaciones sencillas no se requiere la intervención del usuario, pero en otros casos, os aseguro que será necesario modificar manualmente el código que pueda resultar problemático para la migración a ARC.

Espero que este artículo al menos os sirva de introducción a esta nueva metodología de trabajo que Apple ha introducido con ARC.



6 Comentarios

  1. Hola Carlos,

    Ya esta corregido! Muchas gracias por tus comentarios y por el aviso!

    Un abrazo.

  2. Muy interesante. Felicitaciones por tu blog.

  3. Muy Util. Gracias

  4. Me ha servido mucho esta información, gracias!!

  5. “Aunque ARC hace mucho del trabajo de gestión de memoria por nosotros, no debemos pensar que podemos olvidarnos por completo de dicha gestión. Si tenemos punteros que ya no estamos utilizando, y olvidamos cambiar el valor de los mismos a NIL, éstos permanecerán en memoria ocasionando los mismos problemas de recursos que teníamos antes de ARC.”

    Hola Miguel! Queria hacerte una pregunta en cuanto a ARC y pensé que este podría ser el lugar… Tengo una aplicación que usa ARC y modalviewController/dismiss para pasar de una vista a otra. El caso es que creo que debo estar haciendo algo mal porque al depurar utilizando “Allocations” compruebo como al salir de una vista, ésta no se elimina de la memoria, produciendo pasado un tiempo de ejecución el colapso de la misma.
    Según he leido por ahi, ocurre igual si utilizamos el Navigation Controller, incluso con Storyboards o con addSubview/removeFromSuperview. Sin haber encontrado solución alguna al problema. Se te ocurre algo?
    Muchísimas gracias,
    Decirte también que esperamos ansiosos tu próxima entrada en el blog ;-) un saludo

Escribir un comentario

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>