2010-04-26 9 views
6

Digamos que tengo una clase de vista de tabla que enumera 100 objetos Foo. Dispone de:¿Está bien que varios objetos retengan el mismo objeto en Objective-C/Cocoa?

 
@property (nonatomic, retain) NSMutableArray* fooList; 

y llenarlo con Foos como:

 
self.fooList = [NSMutableArray array]; 
while (something) { 
    Foo* foo = [[Foo alloc] init]; 
    [fooList addObject:foo]; 
    [foo release]; 
} 

Primera pregunta: ¿porque el NSMutableArray se marca como retener, eso significa que todos los objetos en su interior se conservan también? ¿Estoy agregando correctamente el foo y liberando la copia local después de que se ha agregado a la matriz? ¿O me estoy perdiendo una llamada retener?

Entonces, si el usuario selecciona una fila específica en la tabla y quiero mostrar una vista Foo detalle que llamo:

 
FooView* localView = [[FooView alloc] initWithFoo:[self.fooList objectAtIndex:indexPath.row]]; 
[self.navigationController pushViewController:localView animated:YES]; 
[localView release]; 

Ahora la clase FooView tiene:

 
@property (nonatomic, retain) Foo* theFoo; 

por lo que ahora AMBOS la matriz se aferra a ese Foo, así como a FooView. Pero eso parece estar bien ¿no? Cuando el usuario presiona el botón Atrás se llamará a dealloc en FooView y se llamará a [la versión de Foo]. Luego, se golpea otro botón de retroceso y se llama a dealloc en la clase de vista de tabla y se llama a [lanzamiento de fooList].

Se podría argumentar que la clase FooView debe tener:

 
@property (nonatomic, assign) Foo* theFoo; 

frente a retener. Pero a veces la clase FooView se llama con un Foo que no está también en una matriz. Así que quería asegurarme de que estaba bien tener dos objetos agarrados al mismo otro objeto.

Respuesta

4

Como dicen otros, lo que está haciendo es correcto, y el código me parece correcto. Tengo decenas de referencias al mismo objeto en mi código y siempre que haya equilibrado todas las publicaciones y publicaciones, todo funciona bien.

Para agregar un poco más de detalle ...usted pregunta:

porque NSMutableArray está marcado como retener, lo que significa que todos los objetos que contiene se conservan también.

Estas son dos cosas diferentes. Todas las clases de colección (Diccionarios, Matrices, Conjuntos) retienen automáticamente las cosas que les agregas y liberan sus objetos de contenido cuando el objeto de colección se desasigna. (En el caso de NSMutableArray, el objeto de contenido se libera si lo quita individualmente de la matriz, o cuando desasigna toda la matriz.)

Esto no tiene nada que ver con si el objeto de la colección en sí se conserva o se asigna como propiedad. Lo único que debe considerar es que si su política para la propiedad del objeto de colección no es correcta, es posible que se lance antes o después de lo que cree y que las cosas se salgan de balance.

Como dicen otros ... lea el memory management guide, y practique. :) Ah, y lea el código de otras personas también desde esta perspectiva y trate de comprender cómo y por qué están haciendo su gestión de memoria.

Otra cosa pequeña ... para cada propiedad retenida, asegúrese de tener una llamada de liberación en el método dealloc del objeto.

+0

Typo: "... y liberan sus objetos de contenido cuando se lanza el objeto de colección." Los objetos en colecciones no se liberan hasta que la colección * se desasigna *. – JeremyP

+0

Gracias, corregido. Aunque se podría argumentar que por "liberado" quise decir "el último lanzamiento, por el cual el conteo de retención va a cero, lo que desencadena el desalojo": P, pero solo decir "dealloc" es más claro en ese contexto. – Jaanus

4

Sí, está bien. Ese es el objetivo de un sistema de gestión de memoria de recuento de referencias.

5

Para responder a su pregunta principal, sí puede tener múltiples objetos conservando una instancia. Ese es exactamente el punto de referencia: administración de memoria contada. Echa un vistazo a la Cocoa Memory Management Programming Guide para obtener más información. Luego vuelve a leerlo. Tiene todas las respuestas y será tu mejor amigo.

Básicamente, el envío de un mensaje -retain indica que el remitente es el "dueño" del receptor en el sentido de que el receptor no debe cancelar la asignación hasta que todos los propietarios han publicado su propiedad. Por lo tanto, las instancias individuales no necesitan saber (ni deberían importar) si existen otros propietarios. Retenga todo lo que necesite para mantener y libérelo cuando haya terminado con él. Cuando todos los propietarios de han liberado su propiedad, una intsance puede ser desasignada.

En una nota lateral,

@property (retain,readwrite) NSMutableArray *myArray; 

declara que la clase declarar esta propiedad conservará la instancia NSMutableArray. NSArray, NSDictionary y NSSet (y sus subclases mutables) conservan siempre sus contenidos.

Cuestiones relacionadas