it-swarm.it

Come funziona il pool di autorelease NSAutoreleasePool?

A quanto ho capito, qualsiasi cosa creata con alloc , new , o copy deve essere rilasciata manualmente. Per esempio:

int main(void) {
    NSString *string;
    string = [[NSString alloc] init];
    /* use the string */
    [string release];
}

La mia domanda, però, non sarebbe altrettanto valida ?:

int main(void) {
    NSAutoreleasePool *pool;
    pool = [[NSAutoreleasePool alloc] init];
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
    [pool drain];
}
94
James Sumners

Sì, il tuo secondo snippit di codice è perfettamente valido.

Ogni volta che un'autorelease viene inviato a un oggetto, viene aggiunto al pool di autorelease più interno. Quando il pool viene scaricato, invia semplicemente -release a tutti gli oggetti nel pool.

I pool di autorelease sono semplicemente una comodità che consente di rinviare l'invio -release fino a "dopo". Quel "più tardi" può accadere in diversi punti, ma il più comune nelle app della GUI di Cocoa è alla fine del ciclo del ciclo di esecuzione corrente.

65
kperryua

NSAutoreleasePool: drain vs. release

Dato che la funzione di drain e release sembra causare confusione, potrebbe valere la pena chiarire qui (anche se questo è trattato in la documentazione ...).

A rigor di termini, dal punto di vista del grande quadro drain è not equivalente a release:

In un ambiente conteggiato di riferimento, drain esegue le stesse operazioni di release, quindi i due sono equivalenti in tal senso. Per sottolineare, questo significa che non perde un pool se si utilizza drain piuttosto che release.

In un ambiente garbage-raccolto, release è un no-op. Quindi non ha alcun effetto. drain, d'altra parte, contiene un suggerimento al collector che dovrebbe "raccogliere se necessario". Pertanto, in un ambiente garbage-collected, l'utilizzo di drain aiuta gli sweep della raccolta del saldo di sistema.

37
mmalc

Come già sottolineato, il secondo snippet di codice è corretto.

Vorrei suggerire un modo più succinto di utilizzare il pool di autorelease che funziona su tutti gli ambienti (conteggio ref, GC, ARC) ed evita anche la confusione di drain/release:

int main(void) {
  @autoreleasepool {
    NSString *string;
    string = [[[NSString alloc] init] autorelease];
    /* use the string */
  }
}

Nell'esempio sopra, si noti il ​​blocco @autoreleasepool. Questo è documentato qui .

17
Neovibrant

No, ti sbagli. La documentazione afferma chiaramente che sotto non-GC, -drain è equivalente a -release, il che significa che NSAutoreleasePool sarà non essere trapelato.

7
kperryua

Ho trovato questo collegamento ha fornito la migliore spiegazione su quando e come utilizzare NSAutoReleasePool: AutoReleasePool

1
Wayne Lo

l'invio di autorelease anziché di rilascio a un oggetto estende la durata di tale oggetto almeno finché il pool stesso non viene scaricato (potrebbe essere più lungo se l'oggetto viene successivamente mantenuto). Un oggetto può essere inserito nello stesso pool più volte, nel qual caso riceve un messaggio di rilascio per ogni volta che è stato inserito nel pool.

0
Hardik Mamtora

sì il tuo codice è perfetto, se dovessi usare la raccolta dei rifiuti sarebbe sufficiente impostare la stringa su zero quando hai finito. La raccolta dei rifiuti non va bene per le prestazioni della tua app, quindi non ti consiglio di utilizzarla: P

0
Antwan van Houdt

Quello che ho letto da Apple: "Alla fine del blocco pool di autorilease, agli oggetti che hanno ricevuto un messaggio di autorelease all'interno del blocco viene inviato un messaggio di rilascio: un oggetto riceve un messaggio di rilascio per ogni volta che è stato inviato un messaggio di autorelease entro il blocco."

https://developer.Apple.com/library/mac/documentation/cocoa/conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html

0
Gagan_iOS