Domanda

Ogni volta che chiamo questo metodo il mio NSMutableData perde e non riesco a capire come collegarlo. il conteggio dei dati di theData è aumentato di uno dopo che il decoder è stato allocato e inizializzato e non ho idea del perché. Sono bloccato con un conteggio pari a 2 alla fine del metodo e il tentativo di rilasciarlo provoca un arresto anomalo dell'app.

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;


    theData = [NSData dataWithContentsOfFile:inFile];

    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

    venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

    [decoder finishDecoding];

    [decoder release];
}
È stato utile?

Soluzione

Suggerirei di sostituire questa riga:

venueIOList = [[decoder decodeObjectForKey:inKey] mutableCopy];

con:

ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
self.venueIOList = decodedList;

Questo rende chiara la gestione della memoria di decodedList . Si considera buona pratica assegnare variabili di istanza usando un metodo accessor (tranne nei metodi init). Nella tua attuale implementazione, se mai invochi readVenueArchiveFile: una seconda volta sullo stesso oggetto, perderai (come faresti se decodedList ha un valore). Inoltre, puoi inserire la logica di copia nel tuo metodo di accesso e dimenticartene piuttosto che dover ricordare mutableCopy ogni volta che assegni un nuovo valore (supponendo che ci sia una buona ragione per fare comunque una copia mutabile?).

Altri suggerimenti

Riduzione dell'ingombro della memoria di picco

In generale, si ritiene che sia meglio evitare la generazione di oggetti rilasciati automaticamente.

[La maggior parte di questo paragrafo è stata modificata da questa domanda .] Dato che tu in genere (1) non hanno il controllo diretto sulla loro durata, gli oggetti rilasciati automaticamente possono persistere per un tempo relativamente lungo e aumentare inutilmente l'impronta di memoria dell'applicazione. Mentre sul desktop questo potrebbe avere poche conseguenze, su piattaforme più vincolate questo può essere un problema significativo. Su tutte le piattaforme, quindi, e specialmente su piattaforme più vincolate, ove possibile sei fortemente scoraggiato dall'utilizzare metodi che porterebbero a oggetti rilasciati automaticamente e invece incoraggiati a usare il modello alloc / init.

Suggerirei di sostituire questo:

theData = [NSData dataWithContentsOfFile:inFile];

con:

theData = [[NSData alloc] initWithContentsOfFile:inFile];

quindi alla fine del metodo aggiungi:

[theData release];

Ciò significa che theData verrà deallocato prima della chiusura del metodo. Dovresti finire con:

- (void)readVenueArchiveFile:(NSString *)inFile key:(NSString *)inKey
{
    NSMutableData *theData;
    NSKeyedUnarchiver *decoder;

    theData = [[NSData alloc] initWithContentsOfFile:inFile];
    decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];
    ListClassName *decodedList = [decoder decodeObjectForKey:inKey];
    self.venueIOList = decodedList;
    [decoder finishDecoding];
    [decoder release];
    [theData release];

}

Ciò rende chiara la semantica della gestione della memoria e recupera la memoria il più rapidamente possibile.

(1) Puoi prendere il controllo usando i tuoi pool di autorelease locali. Per ulteriori informazioni, consulta Guida alla programmazione della gestione della memoria di Apple .

Non preoccuparti di conservare i conteggi, preoccupati dell'equilibrio all'interno di un metodo. Quello che stai facendo in questo metodo sembra corretto, supponendo che venueIOList sia una variabile di istanza.

Per espandere un po 'la mia risposta: l'archiviatore potrebbe conservare i tuoi dati durante l'operazione di archiviazione e quindi inviare i dati -autorelease al termine invece di -release . Dal momento che non è qualcosa che tu hai fatto, non è qualcosa di cui tu devi preoccuparti.

La fonte definitiva per l'illuminazione della gestione della memoria relativa al refcount è ancora, IMO, " Hold Me, Use Me, Free Me " da Stepwise.

Il tuo codice è corretto; non c'è perdita di memoria.

theData = [NSData dataWithContentsOfFile:inFile];

è equivalente a

theData = [[[NSData alloc] initWithContentsOfFile:inFile] autorelease];

A questo punto theData ha un conteggio di riferimento di 1 (se inferiore, sarebbe deallocato). Il conteggio dei riferimenti verrà automaticamente ridotto ad un certo punto in futuro dal pool di rilascio automatico.

decoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:theData];

L'oggetto decodificatore mantiene un riferimento a Data che incrementa il suo conteggio di riferimento a 2.

Dopo la restituzione del metodo, il pool di rilascio automatico riduce questo valore a 1. Se si rilascia theData alla fine di questo metodo, il conteggio dei riferimenti diventerà 0, l'oggetto verrà deallocato e l'app si arresterà in modo anomalo quando si tenta di usalo.

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