I have a memory management-related question in a multithreaded iPhone application. Let's say we have this method, that is called in a separate thread than the main-UI-thread:
- (BOOL)fetchAtIndex:(NSUInteger)index
{
NSURL *theURL = [NSURL URLWithString:[queryURLs objectAtIndex:index]];
// Pay attention to this line:
NSData *theData = [[NetworkHelper fetchFromNetwork:theURL] retain];
// Some code here...
// Now what should I do before returning result?
//[theData release]; ??
//[theData autorelease]; ??
return YES;
}
As you can see, I'm retaining the NSData
I got back from my network operation. The question is: why shouldn't I release (or autorelease) it at the end of my method?
The only way I made it work is to use retain
at first, and nothing then. If I use any other combination (nothing at all; retain
then release
or autorelease
), my program crashes with EXC_BAD_ACCESS
when I release the thread's NSAutoreleasePool
.
What am I missing?
FYI, here is the main code for the thread:
- (void)threadedDataFetching;
{
// Create an autorelease pool for this thread
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
// Reload data in separate thread
[self fetchAtIndex:0];
// Signal the main thread that fetching is finished
[self performSelectorOnMainThread:@selector(finishedFetchingAll) withObject:nil waitUntilDone:NO];
// Release all objects in the autorelease pool
[pool release]; // This line causes EXC_BAD_ACCESS
}
Thanks for your help!
You must not release things you have not retained yourself (using either retain
or implictly by methods with: init
, new
, or copy
in their name).
If you retain result from fetchFromNetwork
, then you must release it. Both release
and autorelease
should work (don't touch object after release
, it's safest to set fields/variables to nil
after release
).
If you're not keeping the data, then you don't even need to retain it. [NetworkHelper fetchFromNetwork]
should return autoreleased object. Body of fetchFromNetwork
could look like this:
NSData *data = [[NSData alloc] init];
// stuff happens
return [data autorelease];
or
NSData *data = [otherObject dataFromOtherObject];
// stuff happens
return data; // don't (auto)release, since you haven't retained
If in doubt, err on the leaky side and run application via "Leaks" Instruments or LLVM checker.