2010-05-23 19 views
9

Estoy trabajando en un proyecto de iPhone donde me gustaría recuperar un objeto de un NSMutableArray, eliminar el objeto de la matriz y luego utilizarlo. El código es como la siguiente:¿NSArray: lastObject devuelve un objeto liberado automáticamente?

NSMutableArray * array; 
// fill the array 
NSObject * obj = [array lastObject]; 
[array removeLastObject]; 
// do something with obj (in the same function) 

matriz es la única entidad con un retener en el objeto que se está accediendo. ¿Esto es seguro de hacer? Asumiría que esto solo funcionaría si lastObject liberara automáticamente el objeto, algo que no puedo entender si lo hace.

Respuesta

11

por qué no llamar

[array removeLastObject] 

al final de su función? Esa es una liberación/retención menos. Puede hacer que su código sea más legible/menos desordenado.

Para el registro de la Apple documentation:

Like NSArray, instances of NSMutableArray maintain strong references to their contents. If you do not use garbage collection, when you add an object to an array, the object receives a retain message. When an object is removed from a mutable array, it receives a release message. If there are no further references to the object, this means that the object is deallocated. If your program keeps a reference to such an object, the reference will become invalid unless you send the object a retain message before it’s removed from the array. For example, if anObject is not retained before it is removed from the array, the third statement below could result in a runtime error:

id anObject = [[anArray objectAtIndex:0] retain]; 
[anArray removeObjectAtIndex:0]; 
[anObject someMessage]; 
+0

Para hacer que la consecuencia de esto sea clara: Las clases NSArray y NSMutableArray tienen excepciones a la regla general de que los objetos devueltos de métodos cuyos nombres no contengan "nuevo", copiar "o" alloc "devuelven objetos liberados automáticamente. Esto significa que el código en la pregunta original no es seguro. – harms

+0

@harms ¿esa regla no se aplica solo a la creación de objetos? – sylvanaar

+4

@harms:. No hay una regla general de que los objetos devueltos de métodos cuyos nombres no contienen "nueva 'copia' o '' objetos autoreleased retorno alloc La única regla es que no es dueño de un objeto tal – JeremyP

2
NSObject * obj = [array lastObject]; // Just returns an object, its retain count not changed 
[array removeLastObject]; // object receives release message 

Así que si la matriz es la única entidad que retiene el objeto a continuación, después de sacarlo de su retener recuento se convierte en cero y hay que dejarse desasignado. Para trabajar con seguridad con el objeto de que usted debe retener y soltar cuando no se necesita:

NSObject * obj = [[array lastObject] retain]; 
[array removeLastObject]; 
// do something with obj (in the same function) 
[obj release]; 
3

Vale la pena mencionar aquí la Cocoa Memory Management Rules. Si trabaja en un entorno que no es de GC, p. iPhone, siempre vale la pena mencionarlos.

El estado regla fundamental:

You take ownership of an object if you create it using a method whose name begins with “alloc” or “new” or contains “copy” (for example, alloc, newObject, or mutableCopy), or if you send it a retain message. You are responsible for relinquishing ownership of objects you own using release or autorelease. Any other time you receive an object, you must not release it.

Es evidente que no obtuvieron obj con alloc, nuevo ... o algo que contiene la copia. Entonces no eres el propietario.

En su código, el segundo de los corolarios también es relevante:

A received object is normally guaranteed to remain valid within the method it was received in (exceptions include multithreaded applications and some Distributed Objects situations, although you must also take care if you modify an object from which you received another object). That method may also safely return the object to its invoker

He negrita la parte pertinente. Ha modificado la matriz desde la que recibió el objeto, por lo que podría desaparecer. O retiene el objeto antes de eliminarlo de la matriz o eliminarlo una vez que haya terminado con el objeto.

En realidad, usted puede ser que ser seguro, incluso con el código en tu pregunta porque la implementación de NSMutableArray de objectAtIndex de: podría hacer una retener seguido de un disparador automático en el artículo de vuelta. En un entorno multiproceso, esa sería la única forma de garantizar que el objeto siga siendo válido durante el tiempo suficiente como para devolverlo a la persona que llama. Sin embargo, no he visto el código para NSMutableArray, así que no confíe en él.

ETA: Sólo estado buscando en la guía de programación hilo y parece que NSMutableAtrray no retienen, autorelease.

+0

Gracias por la respuesta, esa última línea fue muy útil para saber – Chris

Cuestiones relacionadas