Domanda

Sto attraversando tutta la mia documentazione per quanto riguarda la gestione della memoria e sono un po 'confuso su qualcosa.

Quando usi @Property, crea getter/setter per l'oggetto:

.h: @property (conserva, non atomico) nssstring *mystring

.m: @synthesize mystring

Lo capisco, ma dove mi confongo è l'uso di sé. Vedo una sintassi diversa in diversi blog e libri. Ho visto:

myString = [NSString alloc] initWithString:@"Hi there"];

o

self.myString = [NSString alloc] initWithString:@"Hi there"];

Quindi in Dealloc vedo:

self.myString = nil;

o

[myString release];

o

self.myString = nil;
[myString release];

Su questo sito, qualcuno ha affermato che l'uso di sé aggiunge un altro incremento al conteggio di mantenimento? È vero, non l'ho visto da nessuna parte.

I getter/setter automatici che vengono forniti autolesi?

Qual è il modo corretto di fare tutto questo?

Grazie!

È stato utile?

Soluzione

Se non si utilizza la sintassi DOT non si utilizza alcun setter o getter.

La prossima cosa è che dipende da come la proprietà è stata dichiarata.

Supponiamo che qualcosa del genere:

@property (nonatomic, retain) Article *article;
...
@synthesize article;

Assegnazione qualcosa con cui articolo con

self.article = [[Article alloc] init];

Sovradererà l'istanza restituita da alloc/init e causerà una perdita. Questo perché il setter dell'articolo lo manterrà e rilascerà qualsiasi istanza precedente per te.

Quindi potresti riscriverlo come:

self.article = [[[Article alloc] init] autorelease];

Facendo questo

article = [[Article alloc] init]; 

è anche OK, ma potrebbe comportare una perdita in quanto l'articolo potrebbe già tenere un riferimento a un'istanza. Quindi sarebbe necessario liberare il valore in anticipo:

[article release];
article = [[Article alloc] init]; 

Memoria di liberazione potrebbe essere fatto con

[article release];

o con

self.article = nil;

Il primo accede direttamente al campo, nessun setter/giters coinvolti. Il secondo imposta nullo sul campo usando un setter. Che rilascerà l'istanza corrente, se ce n'è una prima di impostarla su zero.

Questo costrutto

self.myString = nil; 
[myString release];

è troppo troppo, in realtà invia il rilascio a Nil, il che è innocuo ma anche inutile.

Devi solo mappare mentalmente il cappello utilizzando la sintassi DOT utilizza i metodi degli accessori:

self.article = newArticle
// is
[self setArticle:newArticle];

e

myArticle = self.article;
// is
myArticle = [self article];

Alcuni suggerimenti sulla lettura, tutti i documenti ufficiali di Apple:

Il linguaggio di programmazione oggettivo-C

Guida alla programmazione della gestione della memoria

Altri suggerimenti

Quando crei un retain Setter, stai creando qualcosa di simile:

- (void)setString:(NSString *)someString {
    if (someString != string) {
        [string release];
        [someString retain];
        string = someString;
    }
}

Se non si utilizza il setter, il nuovo valore non sta ottenendo quel mantenimento: non "possiedi" quella stringa e perché sono tutti riferimenti, se la stringa originale viene rilasciata, potresti affrontare un riferimento nullo, che porterà a un EXC_BAD_ACCESS. L'uso del setter garantisce che la tua classe ora abbia una copia di quel valore, quindi sì, aumenta il conteggio di mantenimento del nuovo valore. (Si noti che l'uso del getter è una convenzione di OOP: che gli estranei non dovrebbero essere in grado di toccare direttamente l'IVAR. Anche nel tuo getter è possibile modificare il valore, magari restituendo un nsarray quando il tuo ivar è un nsmutablearray, per esempio).

Non dovresti autorelease In un setter: Apple lo ha usato nel loro codice di esempio, ma una cosa da tenere a mente è che i setter sono chiamati molto - milioni di volte, potenzialmente. Tutti quegli oggetti stanno entrando nello stesso pool di autolelease, quindi a meno che tu non crei il tuo e/o lo scarichi regolarmente, avrai un sacco di elementi nella tua piscina, tutti non necessari ma ancora prendendo RAM. Molto meglio a semplicemente release.

Per quanto riguarda Dealloc, rintraccia attraverso quel setter. Se invii un release Direttamente, è ovvio: rilasci quell'oggetto. Ma se scrivi self.string = nil;, quello che stai facendo è questo:

  1. Il valore nullo non è lo stesso, quindi si inserisce il if bloccare
  2. Rilasci il vecchio valore: quello che vuoi fare
  3. Voi retain Nil: i messaggi per nulla non fare nulla e non si blocca
  4. Si imposta nil, il che non occupa alcuna memoria, sulla stringa, che ora è effettivamente vuota

Per una questione di convenzione, uso release nel mio dealloc metodo, perché release Sembra più finale, e dealloc è il metodo finale Chiama il tuo oggetto riceverà. Io uso self.string = nil; In ViewDidUnload e nei metodi di avvertimento di memoria.

Spero che sia di aiuto!

Oltre alla risposta di Nick, i getter/setter sintetizzati non forniscono autolease (btw, qual è la grande idea di farlo? Beh, puoi usare Getter come fabbrica, ma non è un modo comune nell'obiettivo C).

Quindi in Dealloc vedo:

self.mystring = nil;

o

Mystring Release];

o

self.mystring = nil; [Mystring Release];

In Dealloc non importa davvero quale forma di rilascio che stai usando. Ma il buon modo è quello di anabbagliante i tuoi campi quando li rilascia :) Preferisco usare self.myString = nil; in Dealloc

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