2009-07-25 7 views
13

Aquí está el código al que me refiero.¿Qué aumenta el recuento de retención de un objeto?

// Person.h 

@interface Person : NSObject { 
    NSString *firstName; 
    NSString *lastName; 
} 
@end 

// Person.m 

@implementation Person 
- (id)init { 
    if (![super init]) return nil; 
    firstName = @"John"; 
    lastName = @"Doe"; 
} 
@end 

// MyClass.m 

@implementation MyClass 
    ..... 
- (NSArray *)getPeople { 
    NSMutableArray *array = [[NSMutableArray alloc] init]; 

    int i; 
    for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
    } 

    return array; 
} 
    ..... 
@end 

Ahora, sé que no hay administración de memoria en este código de muestra. ¿Qué se requeriría?

En el bucle getPeople, estoy asignando una Persona (retainCount 1), y luego lo agrego a la matriz. El conteo de retención ahora es 2, ¿verdad? Si es dos, ¿debería estar [p release]'ing después de agregarlo a la matriz, con lo que retomar reutilizar a 1?

¿Tengo razón en que es responsabilidad del que llama liberar la matriz devuelta por el método? (Que también liberaría la memoria de la Persona, y sus variables de instancia, asumiendo que sus recuentos están en 1).

He leído el documento de administración de memoria de Apple, pero supongo que lo que no tengo claro es qué es lo que aumenta la retención de un objeto? Aunque creo que capto la idea de quién es la responsabilidad de liberar. Esta es la regla fundamental, según Apple:

tomar posesión de un objeto si se crea empleando un método cuyo nombre comienza con “alloc” o “nuevo” o contiene “copia” (por ejemplo, alloc , newObject o mutableCopy), o si le envía un mensaje de retención. Usted es responsable de renunciar a la propiedad de los objetos que posee mediante el lanzamiento o la liberación automática. En cualquier otro momento que reciba un objeto, no debe liberarlo.

frase de bobDevil "solo preocúpate por los conteos de retención que agregas al elemento de forma explícita" haz clic para mí. Después de leer la política de Propiedad en Apple, esencialmente, el objeto/método que creó el nuevo objeto, es el responsable de liberarlo/interesarlo. ¿Es esto correcto?

Ahora, supongamos que un método, que recibe un objeto y lo asigna a una variable de instancia. Necesito retener el objeto recibido correcto, ya que todavía tengo un interés en él?

Si algo de esto es incorrecto, házmelo saber.

Respuesta

18

Tiene razón en que la cuenta de retención es 2 después de añadirlo a una matriz. Sin embargo, solo debe preocuparse por los recuentos de retención que agrega al elemento de forma explícita.

Retener un objeto es un contrato que dice "No he terminado contigo, no te vayas". Una regla básica (hay excepciones, pero generalmente están documentadas) es que usted es el propietario del objeto cuando asigna un objeto, o crea una copia. Esto significa que le dan el objeto con un conteo retenido de 1 (no lanzado automáticamente). En esos dos casos, debe liberarlo cuando haya terminado. Además, si alguna vez retiene explícitamente un objeto, debe liberarlo.

Por lo tanto, para ser específico de su ejemplo, cuando crea la Persona, tiene una retención de contar con ella. Se agrega a una matriz (que hace lo que con él, no le importa) y después que haya terminado con la persona, de modo que lo suelte:

Person *p = [[Person alloc] init]; //retain 1, for you 
[array addObject:p]; //array deals with p however it wants 
[p release]; //you're done, so release it 

También, como he dicho anteriormente, sólo se poseer el objeto durante alloc o copiar en general, por lo que para ser coherente con eso en el otro lado de las cosas, debe devolver la matriz autoreleased, por lo que la persona que llama del método getPeople no es la propietaria.

return [array autorelease]; 

Editar: correcta, si lo crea, debe liberarlo. Si invierte interés en él (a través de retener) debe liberarlo.

4

Los recuentos de retención aumentan cuando se llama a alloc específicamente, por lo que deberá liberarlo explícitamente.

los métodos de fábrica generalmente le dan un objeto liberado automáticamente (como [NSMutableArray array] - debería conservarlo específicamente para mantenerlo durante un período de tiempo prolongado).

En cuanto a NSArray y NSMutableArray addObject :, alguien más tendrá que comentar. Creo que tratas a las clases como cuadros negros en términos de cómo manejan su propia gestión de memoria como un patrón de diseño, por lo que nunca liberarías explícitamente algo que hayas pasado a NSArray. Cuando se destruye, se supone que maneja la disminución del conteo de retención.

También puede obtener un mantenimiento algo implícito si declara sus ivars como propiedades como @property (retener) suchAndSuchIvar, y usa @synthesize en su implementación. Sintetizar básicamente crea setters y getters para ti, y si llamas (retener) específicamente, el setter va a retener el objeto pasado a él.No es siempre evidente de inmediato, ya que los emisores pueden ser estructurados de esta manera:

Person fart = [[Person alloc] init]; 
fart.firstName = @"Josh"; // this is actually a setter, not accessing the ivar 
          // equivalent to [fart setFirstName: @"Josh"], such that 
          // retainCount++ 

Editar:

Y en cuanto a la gestión de memoria, tan pronto como se agrega el objeto a la matriz, que está hecho con él ... así:

for (i = 0; i < 10; i++) { 
     Person *p = [[Person alloc] init]; 
     [array addObject:p]; 
     [p release]; 
    } 

Josh

2

en general, debería/no/se preocupe de la cuenta de retención. Eso está implementado internamente. Solo debe importar si desea "poseer" un objeto reteniéndolo. En el código anterior, la matriz debe poseer el objeto, no usted (fuera del ciclo, ni siquiera tiene referencia, excepto a través de la matriz). Como posee [[Person alloc] init], debe liberarlo.

Así

Person *p = [[Person alloc] init]; 
[array addObject:p]; 
[p release]; 

Además, la persona que llama de "getPeople" no debería poseer la matriz. Esta es la convención. Deberías soltarlo primero.

NSMutableArray *array = [[[NSMutableArray alloc] init] autorelease]; 

Usted querrá leer la documentación de Apple en la gestión de memoria: http://developer.apple.com/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

+0

Josh dice que NSMutableArray está marcado para su liberación automática por defecto? –

+2

Tiene que liberar automáticamente de forma automática un objeto que cree. – mjhoy

Cuestiones relacionadas