zpesk
zpesk

Reputation: 4353

Retaining an object created in an NSThread

I have the following method which is spawned by a call for a new thread (using NSThread):

- (void) updateFMLs {   
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSArray *temp = [[NSArray alloc] initWithArray:someArrayFromAnotherProcess];

    [self performSelectorOnMainThread:@selector(doneLoading:) withObject:temp waitUntilDone:NO];
    [pool release];
}

My doneLoading: method looks like this:

- (void) doneLoading:(NSArray *)obj {
    myArray = [[NSArray alloc] initWithArray:obj copyItems:NO];
}

The contents of myArray become invalid. How can I preserve the contents of myArray so I can use them later in my app?

P.S. myArray is defined in the class header file.

Upvotes: 1

Views: 633

Answers (3)

Ira Cooke
Ira Cooke

Reputation: 1345

An alternative to the options above would be to declare myArray as an atomic property in the header

@property (atomic,retain) NSArray *myArray;

Then in updateFMLs you should be able to simply call the setter from the secondary thread. Obviously this only works if you are willing to pay the performance penalty for an atomic property.

- (void) updateFMLs {
    NSAutoreleasePool *pool - [[NSAutoreleasePool alloc] init];
    NSArray *temp = [[NSArray alloc] initWithArray:someArrayFromAnotherProcess];
    [self setMyArray:temp];
    [temp release];
    [pool drain];
}

Upvotes: 0

Jason
Jason

Reputation: 28590

If your background thread does some work and needs to 'pass' an NSArray to your main thread, then all doneLoading needs to do is:

-(void)doneLoading:(NSArray *)obj
{
    [myArray release]; // release the previous array and its objects
    myArray = [obj retain];
    // now use myArray, refresh tables, etc.
}

There's (likely) no need to make another copy of the array, and that might be the underlying issue. You should also call [temp release] after your performSelector call, since arguments to that are retained already.

If the contents of myArray are becoming valid somehow, then they are being doubly released somewhere. myArray will retain any objects that are added to it. You mentioned that myArray itself is becoming invalid, so try rewriting your background thread and your doneLoading method with this pattern.

Finally you should use [pool drain] in place of [pool release].

Upvotes: 1

Tom Dalling
Tom Dalling

Reputation: 24125

The code you posted looks fine, apart from the memory leak in updateFMLs. You're probably over-releasing the objects somewhere else. I'm guessing it would be wherever someArrayFromAnotherProcess is made.

Upvotes: 0

Related Questions