Si desarrollas para iOS, probablemente haya algo que te hayas preguntado alguna vez.
«¿Por qué el código antiguo de Objective-C está lleno de retain y release?»
Si empezaste con Swift, es posible que abrir código antiguo te haya desconcertado.
Hoy repasaremos la historia de la gestión de memoria en Objective-C: cómo evolucionó de MRC a ARC.
Empecemos por la idea principal.
La gestión de memoria de Objective-C pasó de la época en que los desarrolladores contaban manualmente (MRC) a aquella en que el compilador lo hacía por ellos (ARC).
La recolección de basura se probó brevemente, pero ARC apareció finalmente en 2011 y dejó definido el rumbo.
Veamos cada etapa.
¿Qué es el conteo de referencias? Conceptos básicos de gestión de memoria
Antes de entrar en la historia, fijemos un solo concepto.
El conteo de referencias (reference count).
Imagina que cada objeto tiene un número que cuenta cuántas personas lo están reteniendo.
Si el número es al menos 1, el objeto sigue vivo; cuando llega a 0, se libera de la memoria.
Por eso incrementas el número al retener un objeto (retain) y lo reduces al soltarlo (release).
Esta regla sencilla es la base de la gestión de memoria de Objective-C.
La era de MRC: cuando los desarrolladores contaban manualmente
Antes de ARC, en la era de MRC (Manual Retain Count), las personas gestionaban este número a mano.
Las reglas eran claras. A menudo se memorizaban con el término «NARC».
- Yo soy responsable de los objetos creados con New, Alloc, Retain o Copy
- Los objetos de los que soy responsable deben ejecutar
releaseal terminar de usarlos
El código real tenía este aspecto.
// Al crear un objeto, el conteo de referencias pasa a 1
NSObject *obj = [[NSObject alloc] init];
[obj retain]; // conteo 2
[obj release]; // conteo 1
[obj release]; // conteo 0 → liberar memoria
Ahí surgía el problema.
Si olvidabas release, se producía una fuga de memoria; si liberabas demasiado pronto, tocar un objeto ya desaparecido hacía que la app se cerrara.
El famoso fallo del «objeto zombi».
Tenías que contar mentalmente cuántas referencias tenía el objeto que estabas reteniendo, una tarea realmente agotadora.
autorelease: «Lo soltaré un poco más tarde, no ahora»
La era de MRC también tenía otra situación complicada.
Ocurría cuando un método creaba un objeto nuevo y lo devolvía al exterior.
- (NSString *)greeting {
NSString *msg = [[NSString alloc] initWithString:@"Hola"];
return msg; // Yo lo alloc he creado, así que debería release hacerlo, pero ¿cuándo?
}
Según las reglas, quien llama a alloc debe ejecutar release.
Pero si haces release antes de return, el objeto desaparece antes de que el receptor pueda usarlo. Si no lo haces, hay una fuga.
autorelease apareció para resolver este dilema.
Programa el release para «no ahora, sino dentro de un rato».
Un objeto autoreleased se coloca en una lista de espera llamada autorelease pool y recibe release cuando se vacía el pool, normalmente al terminar una vuelta del run loop.
Así, el receptor podía recibir y usar el objeto de forma segura.
Los constructores de conveniencia como [NSString stringWithFormat:], que devolvían objetos directamente sin alloc, usaban todos este método.
Este autorelease pool sobrevivió en la era de ARC con el nombre de bloque @autoreleasepool. Es una herramienta práctica para los picos de memoria en bucles, así que lo expliqué en otro artículo.
¿Por qué fracasó la recolección de basura?
Apple también conocía este inconveniente.
Por eso, en 2007, Mac OS X 10.5 Leopard introdujo la recolección de basura (GC), que limpiaba la memoria automáticamente como Java.
Parecía cómodo, porque los desarrolladores ya no tenían que escribir retain ni release.
Pero los resultados fueron poco satisfactorios.
Como GC se ejecutaba en segundo plano, la app podía pausarse brevemente en momentos impredecibles. Además, suponía una carga importante para el iPhone, donde el rendimiento y la batería son críticos.
Por eso nunca llegó a introducirse en iOS.
Finalmente, la GC para Mac quedó deprecated a partir de OS X 10.8, en 2012.
La llegada de ARC: el compilador cuenta por ti
Y en 2011, Apple presentó ARC (Automatic Reference Counting) como solución.
Se anunció junto con Xcode 4.2, iOS 5 y OS X 10.7 Lion.
La idea de ARC era ingeniosa.
Se mantenía el conteo de referencias, pero el compilador insertaba automáticamente
retainyreleaseen lugar del desarrollador.
A diferencia de GC, que ejecuta un proceso de limpieza separado en tiempo de ejecución, ARC inserta el código de liberación en los lugares necesarios durante la compilación.
Así, la gestión de memoria se automatizó prácticamente sin coste de rendimiento en tiempo de ejecución.
La comparación entre ambas épocas queda así.
| Categoría | MRC | ARC |
|---|---|---|
| Aparición | Primeros años–2011 | 2011 (iOS 5) |
| retain/release | Escrito manualmente | Insertado automáticamente por el compilador |
| autorelease | Llamada directa | Gestionado por el compilador |
| Riesgo de fugas de memoria | Alto | Muy reducido |
| Coste de rendimiento | Ninguno | Casi ninguno |
Aun así, ARC no es mágico.
Como no puede resolver automáticamente las referencias cíclicas, el desarrollador debe romperlas con referencias débiles como weak o unowned.
Este concepto se mantiene igual en el Swift que usamos hoy.
Preguntas frecuentes (Q&A)
P. ¿Todavía tengo que aprender MRC?
En la práctica, casi nunca escribirás código nuevo con MRC. Sin embargo, pueden preguntarte por ello en bibliotecas antiguas o entrevistas, así que conviene conocer sus principios.
P. ¿También se usa autorelease con ARC?
No tendrás que llamarlo directamente, pero el mecanismo sigue funcionando bajo ARC. Por eso el bloque @autoreleasepool sigue siendo útil.
P. ¿Swift también usa ARC?
Sí, Swift también se basa en ARC. Por eso las referencias cíclicas y el concepto weak son igualmente importantes en Swift.
En resumen, la gestión de memoria de Objective-C evolucionó de «MRC contado a mano → un breve experimento con GC → ARC contado por el compilador».
La gestión automática de memoria que hoy damos por sentada se perfeccionó tras innumerables fallos y pruebas.
Espero que este recorrido sirva como pequeño mapa para quienes estudian desarrollo de iOS. ¡Feliz programación!

