Проблема управления памятью NSArray - PullRequest
0 голосов
/ 12 октября 2010

Вот мой код, который запускается в фоновом потоке:

-(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 ]

3 голосов
/ 12 октября 2010

В вашем коде arrFAQData это просто псевдоним arrLoadedData, поэтому базовый объект будет освобожден «одновременно» (это тот же объект). Вам необходимо сохранить ссылку на arrLoadedData и сохранить ее.

arrFAQData = [arrLoadedData retain];
2 голосов
/ 12 октября 2010

Определите arrFAQData как свойство с ключевым словом retain, затем присвойте его следующим образом:

self.arrFAQData = arrLoadedData;

Это будет retain arrLoadedData при назначении

1 голос
/ 12 октября 2010

В дополнение к ответам выше небезопасно устанавливать arrFAQData из вторичного потока, подобного этому.Основной риск состоит в том, что что-то в главном потоке будет частично выполняться через старое значение arrFAQData, когда значение внезапно изменится.Абсолютный наихудший случай - это что-то вроде середины основного потока:

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

Если вы отпустите то, на что указывает arrFAQData, и добавите что-нибудь еще во вторичный поток, то вы в конечном итоге попытаетесьдля доступа к освобожденной памяти.Точно так же вы не можете сохранить arrFAQData как тот же логический массив и просто скопировать в него новые объекты, так как вы не можете изменять массив во время быстрой итерации.

Параллелизм - слишком сложная тема, чтобы действительно углубляться в неено для быстрого исправления я рекомендую переключить refreshFAQTable на метод, который принимает новый массив в качестве параметра, и изменить код на:

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

Это, очевидно, позволит избежать каких-либо проблем с основным потоком, работающим намассив при этом заменяется.

1 голос
/ 12 октября 2010

В вашем .h файле:

@private
NSArray *_arrFAQData;

@property (nonatomic, retain) NSArray *arrFAQData;

В вашем файле .m:

@synthesize arrFAQData = _arrFAQData;

Тогда в вашем обновлении FAQQache метод:

self.arrFAQData = arrLoadedData;
[arrLoadedData release];

Не забудьте добавить в метод dealloc следующее:

[_arrFAQData release];
...