Comencemos con retain
y release
; autorelease
es realmente solo un caso especial una vez que entiendes los conceptos básicos.
En Cocoa, cada objeto realiza un seguimiento de cuántas veces se hace referencia (específicamente, la NSObject
clase base implementa esto). Al invocar retain
un objeto, le está diciendo que desea aumentar su recuento de referencia en uno. Al llamar release
, le dice al objeto que lo está soltando, y su recuento de referencia disminuye. Si, después de llamar release
, el recuento de referencia ahora es cero, entonces el sistema libera la memoria de ese objeto.
La forma básica en que esto difiere malloc
y free
es que cualquier objeto dado no necesita preocuparse por otras partes del sistema que fallan porque ha liberado la memoria que estaban usando. Suponiendo que todos están jugando y reteniendo / liberando de acuerdo con las reglas, cuando una pieza de código retiene y luego libera el objeto, cualquier otra pieza de código que también haga referencia al objeto no se verá afectada.
Lo que a veces puede ser confuso es conocer las circunstancias bajo las cuales debe llamar retain
y release
. Mi regla general es que si quiero aferrarme a un objeto por un período de tiempo prolongado (por ejemplo, si es una variable miembro en una clase), entonces debo asegurarme de que el recuento de referencias del objeto me conozca. Como se describió anteriormente, el recuento de referencia de un objeto se incrementa al llamar retain
. Por convención, también se incrementa (se establece en 1, realmente) cuando el objeto se crea con un método "init". En cualquiera de estos casos, es mi responsabilidad llamar release
al objeto cuando haya terminado con él. Si no lo hago, habrá una pérdida de memoria.
Ejemplo de creación de objetos:
NSString* s = [[NSString alloc] init]; // Ref count is 1
[s retain]; // Ref count is 2 - silly
// to do this after init
[s release]; // Ref count is back to 1
[s release]; // Ref count is 0, object is freed
Ahora para autorelease
. La liberación automática se usa como una forma conveniente (y a veces necesaria) de decirle al sistema que libere este objeto después de un tiempo. Desde una perspectiva de fontanería, cuando autorelease
se llama, los hilos actuales NSAutoreleasePool
son alertados de la llamada. El NSAutoreleasePool
ahora sabe que una vez que llega una oportunidad (después de la iteración actual del bucle de eventos), se puede llamar release
en el objeto. Desde nuestra perspectiva como programadores, se encarga de llamarnos release
, por lo que no tenemos que hacerlo (y de hecho, no deberíamos).
Es importante tener en cuenta que (de nuevo, por convención) todos los métodos de clase de creación de objetos devuelven un objeto lanzado automáticamente. Por ejemplo, en el siguiente ejemplo, la variable "s" tiene un recuento de referencia de 1, pero una vez que se completa el bucle de eventos, se destruirá.
NSString* s = [NSString stringWithString:@"Hello World"];
Si desea colgarse de esa cadena, deberá llamar retain
explícitamente y luego explícitamente release
cuando haya terminado.
Considere el siguiente bit (muy artificial) de código, y verá una situación en la que autorelease
se requiere:
- (NSString*)createHelloWorldString
{
NSString* s = [[NSString alloc] initWithString:@"Hello World"];
// Now what? We want to return s, but we've upped its reference count.
// The caller shouldn't be responsible for releasing it, since we're the
// ones that created it. If we call release, however, the reference
// count will hit zero and bad memory will be returned to the caller.
// The answer is to call autorelease before returning the string. By
// explicitly calling autorelease, we pass the responsibility for
// releasing the string on to the thread's NSAutoreleasePool, which will
// happen at some later time. The consequence is that the returned string
// will still be valid for the caller of this function.
return [s autorelease];
}
Me doy cuenta de que todo esto es un poco confuso; sin embargo, en algún momento hará clic. Aquí hay algunas referencias para comenzar:
- Introducción de Apple a la gestión de memoria.
- Cocoa Programming para Mac OS X (4a edición) , de Aaron Hillegas, un libro muy bien escrito con muchos ejemplos excelentes. Se lee como un tutorial.
- Si realmente te estás sumergiendo, puedes dirigirte a Big Nerd Ranch . Este es un centro de capacitación dirigido por Aaron Hillegas, el autor del libro mencionado anteriormente. Asistí al curso de Introducción al Cacao allí hace varios años, y fue una excelente manera de aprender.