释放使用initFromFile方法创建的对象时崩溃

时间:2010-10-05 12:12:26

标签: ios objective-c memory-management nscoding

我创建了一个名为'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 个答案:

答案 0 :(得分:2)

这一行:

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