Domanda

Ho creato un oggetto chiamato 'DateTracker' conforme alle NSCoding, in modo che contenga metodi encodeWithCoder e initWithCoder. Quando ho inizializzarlo, che io chiamo il seguente:

DateTracker *currentTracker = [[DateTracker alloc] initFromFile];

Il metodo initFromFile aspetto:

- (id)initFromFile { 
    NSString *filePath = [self dataFilePath];
    if ([[NSFileManager defaultManager] attributesOfFileSystemForPath:filePath error:NULL]) {
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        self = [unarchiver decodeObjectForKey:kDateDataKey];
        [unarchiver finishDecoding];
        [unarchiver release];
        [data release];
    }
    return self;
}

Tuttavia quando provo a chiamare

[currentTracker release];

la mia app si blocca.

Quando eseguo l'applicazione con gli strumenti delle prestazioni per verificare la presenza di perdite di memoria, si lamenta che non sto rilasciando questo oggetto.

Tutte le idee che sto facendo male?

È stato utile?

Soluzione

Questa riga:

self = [unarchiver decodeObjectForKey:kDateDataKey];

sta per dare problemi.

Quello che stai facendo è quello di allocare un oggetto DateTracker ([DateTracker alloc]), quindi creare un nuovo oggetto DateTracker (da -decodeObjectForKey:) e fare il "sé" puntatore riferimento al nuovo oggetto. Ci sono due problemi con questa:

  • non hai più un riferimento al vecchio oggetto, quindi è trapelato
  • il nuovo oggetto non viene mantenuta, così si va via (o causa un crash se si tenta di rilasciarlo)

Direi che l'approccio di avere un oggetto in sé sostituire è un po 'sospetto. Forse farebbe meglio a spostare la variabile filePath al di fuori dell'oggetto DateTracker, ed estrarlo da qualcosa come:

DateTracker *currentTracker = [[DateTracker unarchiveFromFile:filePath] retain];

dove unarchiveFromFile: è un metodo di classe che fa in sostanza quello initFromFile ha fatto, senza fare confusione con self:

+ (DateTracker*)unarchiveFromFile:(NSString *)filePath { 
    DateTracker *result = nil;
    if ([[NSFileManager defaultManager] attributesOfFileSystemForPath:filePath error:NULL]) {
        NSData *data = [[NSMutableData alloc] initWithContentsOfFile:filePath];
        NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
        result = [unarchiver decodeObjectForKey:kDateDataKey];
        [unarchiver finishDecoding];
        [unarchiver release];
        [data release];
    }
    return result;
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top