Desarrollo iOS: Introducción a Automatic Reference Counting

Una de las novedades más importantes relacionadas al nuevo XCode 4.2 es el soporte para Automatic Reference Counting (ARC) en iOS. Para los que hayan programado en Mac, sabrán de qué se trata. Sino, se los cuento. Desde ahora tenemos dos formas de administrar el ciclo de vida de los objetos:

  • La forma de siempre, en la que nosotros somos los responsables de hacer retain/release/autorelease/dealloc
  • La nueva forma ARC, en la que “el sistema” se encarga de destruir los objetos cuando no se utilizan más. 
  • ¿Cómo es esto? ¿El sistema puede saber cuando destruir los objetos? la respuesta es si, ayudados por nosotros, desde luego, que debemos indicarle el comportamiento que tendrán los objetos. 

    ARC implica que, según el uso de los objetos, el compilador sabrá cuando aumentar o disminuir el contador de referencia de los objetos. Y cuando éste llega a cero, el compilador destruirá la instancia. 


    Cuando creamos un proyecto con XCode 4.2, veremos un nuevo checkbox en el que indicamos si queremos usar ARC o no. Esto impacta en la generación automática de código y en la compilación propiamente dicha. Por ello, con ARC habilitado, tendremos que usar si o si el nuevo compilador LLVM 3.0, que es el default para Xcode 4.2. 

    Los nuevos Lifetime Qualifiers

    Con el nuevo esquema de ARC, no tendremos que pensar más en los objetos en términos de retener y liberar, sino que debemos pensar en el grafo de objetos y la relación entre ellos. Por ello, dejaremos de usar los calificadores retain, release y autorelease. Es el nuevo compilador quien se encargará de generar solito llamadas a retain/release según vea cómo es el uso de los objetos. En definitiva, ya no es más nuestra responsabilidad hacerlo. Tal es así que no deberemos implementar más el método dealloc, imaginen que no tiene sentido destruir objetos en forma “manual” como venimos haciendo desde siempre.

    Ahora, nuestra responsabilidad pasa por indicarle al compilador cuándo un objeto se usa en forma weak o strong. Esto es así tanto para las propiedades como para las variables.

    En las propiedades, strong es análogo al retain:

    // Sin ARC escribimos:

    @property(retain) Clase *objeto;

    // en cambio con ARC:

    @property(strong) Clase *objeto;

    Y weak es similar a assign, con la salvedad que, cuando un objeto es automáticamente destruido, el puntero pasa a valer nil (zeroing weak reference):

    // Sin ARC escribimos:

    @property(assign) Clase *objeto;

    // en cambio con ARC:

    @property(weak) Clase *objeto;

    Respecto a las variables, por defecto son todas strong (keyword __strong).

    Por ejemplo:

    NSString *string = [[NSString alloc] initWithFormat:@”Nombre: %@”, [self Nombre]];

    NSLog(@”string: %@”, string);}

    es una construcción correcta que al finalizar el método liberará el objeto ‘string’ (como si tuviera un autorelease, verdad?).

    En cambio, si definimos al ‘string’ como weak (keyword __weak), el compilador destruirá el objeto inmediatamente de construirlo y el NSLog mostrará nil:

    NSString __weak *string = [[NSString alloc] initWithFormat:@”Nombre: %@”, [self Nombre]];

    NSLog(@”string: %@”, string);

    Se imaginarán que la forma de referenciar los outlets de los objetos creados con Interface Builder también sufren un cambio de pattern. En general, salvo excepciones, debemos considerarlos weak:

    @property (weak) IBOutlet UIButton *btnOK;

    También hay un cambio en la escritura de los Autorelease Pools. No se usa más la clase NSAutoReleasePool, sino que se define una nueva construcción a tal efecto:

    @autoreleasepool {

    // Código, como un loop que crea un gran número de objetos temporales

    }

    Los cambios continúan y escapan a esta introducción, pero al menos quería mencionarles los conceptos importantes y primarios a tener en cuenta.

    Conclusiones

    La ventaja de ARC es obvia: facilitar la programación. Realmente le quita al desarrollador el pensar en la destrucción de los objetos, lo que impacta directamente en una calidad de software mejor, ya que habrá menor cantidad de resource leaks. La parte mala es que debemos migrar librerías y controllers que tengamos desarrollados. Lo bueno es que la migración puede hacerse en forma automática con XCode 4.2. Es algo que debemos experimentar y revisar que tal sucede.

    Si quieren comenzar con este tema, les recomiendo leer la documentación de Apple y “jugar” con todo esto, creando proyectos y probando como se comporta ARC con objetos locales, datamembers y propiedades. Luego, si nos sentimos cómodos, revisar el tema de la migración.

    ARC puede utilizarse con iOS 4 o 5. Esto significa que es factible migrar un proyecto actual que tengamos en producción, a menos que siga siendo compatible con iOS 3.x.

    Un artículo de Angel Traversi

    0 0 votos
    Article Rating
    Subscribe
    Notify of
    2 Comments
    Oldest
    Newest Most Voted
    Opiniones Inline
    Ver todos los comentarios
    Anónimo
    Anónimo
    12 years ago

    Me encanta ver este tipo de articulillos que vais poniendo sobre desarrollo y desde aquí os animo a seguir 😉

    Ahora un par de pequeñas puntualizaciones:

    – Como bien dice el artículo, el compilador es en gran parte el responsable de que ARC funcione, pero el runtime también tiene su parte y para usar __weak tal y como se describe en el artículo es necesario tener iOS 5 porque el runtime de iOS 4 no permite la asignación automática a nil. En iOS 4 se puede utilizar __unsafe_unretained, que no iguala a nil el objeto. En el caso de las propiedades declaradas (@property), en vez de usar “weak” se usaría “assign”.

    – En un mismo proyecto, con el debido cuidado, se pueden mezclar librerías y partes hechas con Y sin ARC, por lo que aquellos que tiren de librerías de terceros aún tienen su oportunidad de, al menos, migrar su parte.

    Saludos y seguid así 😉

    JavierHZ

    Anónimo
    Anónimo
    12 years ago

    Hola JavierHZ, gracias por el aporte!

    2
    0
    Me encantaría saber tu opinión, por favor, deja un comentariox
    ()
    x