NSArray Memory-Management Issue
Here is my co开发者_StackOverflow社区de that is being run in a background thread:
-(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];
}
My issue is that it seems the contents of arrFAQData
is being released when arrLoadedData
is released. This DOES makes sense to me, but I need to figure out how to retain this data into my IVAR while allowing me to release the local variable, arrLoadedData
?
Thanks for your help!
In your code, arrFAQData
is just an alias of arrLoadedData
, so the underlying object will be released "at the same time" (it's the same object). You need to retain a reference to arrLoadedData
, and store that.
arrFAQData = [arrLoadedData retain];
Define arrFAQData
as a property with a retain
keyword, then assign it like this:
self.arrFAQData = arrLoadedData;
This will retain
arrLoadedData
on assignment
In your .h file:
@private
NSArray *_arrFAQData;
@property (nonatomic, retain) NSArray *arrFAQData;
In your .m file:
@synthesize arrFAQData = _arrFAQData;
Then in your updateFAQCache method:
self.arrFAQData = arrLoadedData;
[arrLoadedData release];
Don't forget to add the following in the dealloc
method:
[_arrFAQData release];
In addition to the replies above, it's unsafe to set arrFAQData from a secondary thread like that. The main risk is that something in the main thread will be part way through doing something with the old value of arrFAQData when suddenly the value changes. Absolute worst case is something like being in the middle of this on the main thread:
for(id object in arrFAQData)
{
... something ...
}
If you release what arrFAQData is pointing to and put something else in on the secondary thread then you'll end up trying to access deallocated memory. You similarly can't keep arrFAQData as the same logical array and just copy the new objects into it since you may not modify an array while fast iterating.
Parallelism is too complicated a topic to really go into in depth, but as a quick fix, I recommend switching refreshFAQTable to a method that takes a new array as a parameter, and altering your code to:
[self performSelectorOnMainThread:@selector(refreshFAQTable:) withObject:arrLoadedData waitUntilDone:YES];
That'll obviously avoid any problems with the main thread operating on the array at the same time it is replaced.
精彩评论