Domanda

Ancora un po 'confuso circa la gestione della memoria Objective-C. Credo che la mia confusione deriva da ciò che esattamente l'autorelease significa.

NSString *theBackendResponse = [[NSString alloc] initWithData:receivedData encoding:NSASCIIStringEncoding];
NSDictionary *accountDictionary = [theBackendResponse propertyList];
[viewController setAccountDictionary:accountDictionary];

Ora, che cosa devo fare con l'accountDictionary nel metodo setAccountDictionary del mio controller della vista? In questo momento ho appena impostato l'istanza variabile "accountDictionary" a tutto ciò che viene restituito. Devo impostare ad un conservato uno, e poi rilasciare quello che è tornato? Quale dovrebbe essere il mio codice setter blocco simile, dato che il metodo PropertyList di NSString è autoreleased?

A proposito, se io rilascio theBackendResponse, perderò l'accountDictionary? Io non presumo ...

È stato utile?

Soluzione

La chiamata [objectInstance autorelease] aggiunge un oggetto alla NSAutoreleasePool corrente. Quando quella piscina riceve un messaggio drain, invia un release a tutti gli oggetti nel pool. Se uno qualsiasi di tali oggetti retainCount raggiunge 0, essi si rilasciano in quel punto. Lo scopo di autorelease è quello di permettere di contrassegnare un oggetto per essere rilasciato "po 'di tempo in futuro". Ciò è particolarmente utile per le cose come i metodi che restituiscono un oggetto appena allocato ma vogliono rilasciarlo in modo che il chiamante non deve assumere la proprietà dell'oggetto restituito. Un metodo potrebbe assomigliare a questo:

- (id)myMethod {
    id myObj = [[SomeClass alloc] init];

    ...

    return [myObj autorelease];
}

Il chiamante di myMethod allora retain il valore restituito se volevano assumere la proprietà del valore restituito o ignorarlo, se non. Quando il NSAutoreleasePool corrente viene svuotato, myObj otterrà un messaggio di rilascio. Se non ci sono altri oggetti possiedono esso (cioè hanno inviato un messaggio retain), si otterrà deallocato.

Tutto questo è spiegato nel cacao Memory Management Guida di programmazione . Anche se avete già letto, vale sempre la pena un'altra lettura.

Quindi, per rispondere alle vostre domande:

In primo luogo, si dovrebbe rilasciare theBackendResponse. Potrai perdere la memoria se non lo fai. Non hai bisogno di sapere che cosa accountDictionary fa con la stringa: se ha bisogno di mantenere un riferimento avrà mantenuto theBackendResponse. Hai una proprietà di theBackendResponse perché alloc'd esso, quindi è necessario rinunciare a che la proprietà (via release o indirettamente tramite autorelease).

In secondo luogo, è necessario mantenere o copiare l'argomento per setAccountDictionary: se si desidera mantenere, rispettivamente, un riferimento a tale oggetto o il valore. Il metodo standard setter simile a questa (supponendo che non hai bisogno di semantica atomiche):

-(void)setAccountDictionary:(NSDictionary*)newDict {
  if(newDict != accountDictionary) {
    id tmp = accountDictionary;
    accountDictionary = [newDict copy]; //Since newDict may be mutable, we make a copy so that accountDictionary isn't mutated behind our back.
    [tmp release];
  }
}

Si deve anche ricordare a release accountDictionary nel metodo dealloc:

- (void)dealloc {
    [accountDictionary release];
    [super dealloc];
}

Dal momento in cui sembra essere utilizzando NSViewController, presumo che sei su Leopard (OS X 10.5), nel qual caso, si dovrebbe probabilmente essere utilizzando @property e il @synthesized getter / setter, se possibile. Per fare questo, aggiungere un

@property (copy,readwrite) NSDictionary * accountDictionary; 

dichiarazione alla @interface di classe. E aggiungere una direttiva @synthesize accountDictionary; nel blocco @implementation per la classe di controllo.

Altri suggerimenti

In generale, un oggetto o di un metodo non dovrebbe avere a cuore come un altro è la memoria di gestione. Il fatto che qualcun altro ha autoreleased qualcosa è irrilevante per voi. E 'più semplice pensare al concetto di proprietà . Così retain ed alcuni altri metodi reclama diritti di proprietà, e release e autorelease rinunciare ad essa. Se un oggetto ha bisogno di mantenere un riferimento a un altro, dovrebbe rivendicare la proprietà per tutto il tempo di cui ha bisogno. Così, i metodi setter di solito o mantenere o copiare il nuovo valore e rilasciare o autorelease il vecchio valore.

Vi consiglio vivamente la lettura le linee guida di gestione della memoria di cacao . Non sono tutti così a lungo o complicato, ed è molto importante per capirle.

Il metodo di accesso set dovrebbe sempre copy / retain il valore in ingresso prima di rilasciare il vecchio, nel caso in cui il valore precedente è l'unico oggetto che possiede il nuovo valore:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    id old = accountDictionary;
    accountDictionary = [newDict copy];
    [old release];
}

Se accountDictionary cui newDict e il conteggio conservarlo per newDict è stato 1, la chiamata a [accountDictionary release] prima della chiamata a [newDict copy] causerebbe il conteggio mantenere a avuto modo di 0 e quindi rilasciare newDict.

Come esempio di codice errato, in cui rilasciamo vecchio dizionario e quindi copiare il nuovo dizionario:

-(void)setAccountDictionary:(NSDictionary*)newDict {
    [accountDictionary release];
    accountDictionary = [newDict copy];
}

e hanno il seguente codice:

NSDictionary *dict = [obj accountDictionary];
[obj setAccountDictionary:dict];

E 'forzato, ma dimostra che nel setter, accountDictionary e newDict si riferiscono alla stessa istanza. Se il conteggio di conservare è 1, la linea [accountDictionary release] diminuirà il conteggio di conservare a 0, e quindi rilasciare l'istanza dalla memoria. [newDict copy] ora riferimento a un'istanza valido.

di Apple descrive diversi concetti in sede di attuazione di accesso: gestione della memoria Accessor metodi
Se è possibile utilizzare Objective-C 2.0, vorrei andare con proprietà e sintassi del punto. Le proprietà sono di nuovo in Objective-C 2.0 e forniscono automaticamente la generazione di accesso.
Nel file .h:

@property (retain) NSDictionary* accountDictionary;

Per l'attuazione:

@synthesize accountDictionary;

Sintetizzare genera metodi di accesso per il vostro NSDictionary. (Se si desidera fornire la propria implementazione, si potrebbe anche farlo)

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top