2010-05-23 11 views
9

Sto lavorando a un progetto iPhone in cui desidero recuperare un oggetto da un NSMutableArray, rimuovere l'oggetto dall'array e quindi utilizzarlo in un secondo momento. Il codice è simile al seguente:NSArray: lastObject restituisce un oggetto autoreleased?

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

array è l'unica entità con una conservazione sull'oggetto a cui si accede. È sicuro farlo? Suppongo che questo funzionerebbe solo se lastObject ha autorizzato l'oggetto che è qualcosa che non riesco a capire se lo fa.

risposta

11

perché non chiamare

[array removeLastObject] 

alla fine della vostra funzione? Questo è un numero in meno di rilascio/mantenimento. Potrebbe rendere il tuo codice più leggibile/meno ingombrante.

Per la cronaca il 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

Per rendere la conseguenza di questa chiara:. Le classi NSArray e NSMutableArray hanno eccezioni alla regola generale che oggetti restituiti dai metodi i cui nomi non contengono "nuova, 'copia' o 'allocate' ritorno oggetti autoreleased Questo significa che il codice di nella domanda originale non è sicuro – harms

+0

@harms questa regola non si applica solo alla creazione dell'oggetto? – sylvanaar

+4

@harms: non esiste una regola generale per gli oggetti restituiti da metodi i cui nomi non contengono "nuovo", "copia" o "alloc" restituiscono oggetti autoreleased L'unica regola è che non possiedi un oggetto del genere – JeremyP

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

Quindi, se la matrice è l'unica entità che mantengono l'oggetto poi, dopo la rimozione sua mantenere conteggio diventa zero e dovrebbe ottenere deallocato. Per lavorare in sicurezza con quell'oggetto si dovrebbe mantenere e rilasciarlo quando non è necessaria:

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

Vale la pena menzionare il Cocoa Memory Management Rules qui. Se lavori in un ambiente non GC, ad es. iPhone, vale sempre la pena menzionarli.

La fondamentale regola di Stato:

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.

Chiaramente non ha ottenuto obj con alloc, nuovo ... o qualcosa contenente copia. Quindi non lo possiedi.

Nel codice, il secondo dei corollari è anche rilevante:

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

ho grassetto la parte interessata. Hai modificato la matrice da cui hai ricevuto l'oggetto, quindi potrebbe andare via. O si conserva l'oggetto prima di rimuoverlo dall'array o si rimuove dopo aver terminato con l'oggetto.

In realtà, si potrebbe essere al sicuro anche con il codice nella tua domanda, perché l'implementazione di NSMutableArray di objectAtIndex: potrebbe fare un Retain seguito da un autorelease sulla voce di ritorno. In un ambiente multithread che sarebbe l'unico modo per garantire che l'oggetto rimanga valido per un tempo sufficiente a restituirlo al chiamante. Tuttavia, non ho visto il codice per NSMutableArray, quindi non fare affidamento su di esso.

ETA: Basta osservare la guida alla programmazione dei thread e sembra che NSMutableAtrray non mantenga, autorelease.

+0

Grazie per la risposta, quell'ultima riga era molto utile da sapere – Chris

Problemi correlati