Сбой при освобождении объекта, созданного методом initFromFile - PullRequest
0 голосов
/ 05 октября 2010

Я создал объект с именем DateTracker, который соответствует NSCoding, поэтому он содержит методы encodeWithCoder и initWithCoder.Когда я инициализирую его, я вызываю следующее:

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

Метод initFromFile выглядит следующим образом:

- (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;
}

Однако, когда я пытаюсь вызвать

[currentTracker release];

мое приложение вылетает.

Когда я запускаю приложение с инструментами производительности для проверки утечек памяти, он жалуется, что я не освобождаю этот объект.

Есть идеи, что я делаю не так?

1 Ответ

2 голосов
/ 05 октября 2010

Эта строка:

self = [unarchiver decodeObjectForKey:kDateDataKey];

доставит вам проблемы.

Что вы делаете, это выделяете объект DateTracker ([DateTracker alloc]), а затем создаете новый DateTrackerобъект (-decodeObjectForKey:) и указатель «self» ссылается на новый объект.С этим связаны две проблемы:

  • у вас больше нет ссылки на старый объект, поэтому утечка
  • нового объекта не сохраняется, поэтому он исчезает (или вызываетсбой, если вы попытаетесь его освободить)

Я бы сказал, что подход к замене объекта сам по себе немного подозрительный.Возможно, вам лучше переместить переменную filePath за пределы объекта DateTracker и разархивировать ее следующим образом:

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

, где unarchiveFromFile: - это метод класса, который, по сути, initFromFile сделал, не возиться с 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;
}
...