NSArray内存管理问题

时间:2010-10-12 15:37:32

标签: iphone objective-c memory-management nsarray

以下是我在后台线程中运行的代码:

-(void)updateFAQCache {

    NSAutoreleasePool *objPool = [[NSAutoreleasePool alloc] init];

    // Grab the new plist
    NSMutableArray *arrLoadedData = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:@"http://myurl.com/"]];

    // If the data is not Nil, update the table view and cache with the new data
    if (arrLoadedData != Nil) {

        // Merge the new data into our IVar
        arrFAQData = arrLoadedData;

        // Update the table view
        [self performSelectorOnMainThread:@selector(refreshFAQTable) withObject:Nil waitUntilDone:NO];

        // Save the new data to the cache
        [arrFAQData writeToFile:self.strFAQCacheLocation atomically:YES];

    }

    [arrLoadedData release];

    [objPool release];

}

我的问题是,arrFAQData发布后似乎正在发布arrLoadedData的内容。这对我来说很有意义,但我需要弄清楚如何将这些数据保留到我的IVAR中,同时允许我发布局部变量arrLoadedData

感谢您的帮助!

4 个答案:

答案 0 :(得分:3)

在您的代码中,arrFAQData只是arrLoadedData的别名,因此底层对象将“同时”释放(它是同一个对象)。您需要保留对arrLoadedData的引用,并存储该内容。

arrFAQData = [arrLoadedData retain];

答案 1 :(得分:2)

arrFAQData定义为具有retain关键字的属性,然后将其指定为:

self.arrFAQData = arrLoadedData;

分配时retain arrLoadedData

答案 2 :(得分:1)

在你的.h文件中:

@private
NSArray *_arrFAQData;

@property (nonatomic, retain) NSArray *arrFAQData;

在您的.m文件中:

@synthesize arrFAQData = _arrFAQData;

然后在你的updateFAQCache方法中:

self.arrFAQData = arrLoadedData;
[arrLoadedData release];

不要忘记在dealloc方法中添加以下内容:

[_arrFAQData release];

答案 3 :(得分:1)

除了上面的回复之外,从这样的辅助线程设置arrFAQData是不安全的。主要风险是,当突然值变化时,主线程中的某些东西将成为使用arrFAQData的旧值做某事的一部分。绝对最坏的情况就像在主线程中处于这个中间:

for(id object in arrFAQData)
{
    ... something ...
}

如果你发布arrFAQData指向的内容并在辅助线程上放入其他内容,那么你最终会尝试访问释放的内存。您同样不能将arrFAQData保持为相同的逻辑数组,只是将新对象复制到其中,因为您可能无法在快速迭代时修改数组。

并行性是一个太复杂的主题,无法深入探讨,但作为一个快速修复,我建议将refreshFAQTable切换到一个方法,该方法将新数组作为参数,并将代码更改为:

[self performSelectorOnMainThread:@selector(refreshFAQTable:) withObject:arrLoadedData waitUntilDone:YES];

这显然可以避免在替换它的同时对阵列上运行的主线程出现任何问题。