Reputation: 6046
I searched for the past couple hours reading dozens of posts on the topic of memory management in objective-C and I just don't get it. Sorry. I am doing my best!
What I am looking for at the moment is the answer to how to return an object from a method which calls 'executeFetchRequest'.
Here is some code...
+ (Player *)loadPlayerWithPredicate:(NSString *)name:(NSInteger)index
{
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Player" inManagedObjectContext:managedObjectContext];
[request setEntity:entity];
// Set filter predicate
NSString *strFilter = [NSString stringWithFormat:@"%@ = %d", name, index];
[request setPredicate:[NSPredicate predicateWithFormat:strFilter]];
// Create the sort descriptors array
NSSortDescriptor *sorter = [NSSortDescriptor sortDescriptorWithKey:name ascending:YES];
[request setSortDescriptors:[NSArray arrayWithObject:sorter]];
NSError *error = nil;
Player *player = nil;
NSArray *array = [managedObjectContext executeFetchRequest:request error:&error];
if ([array count] == 1)
{
player = [array objectAtIndex:0];
//[player retain]; // ???
}
[request release];
return player;
}
But what I really need is for the "player" object to stick around after the method returns.
How can I make 'player' live after being returned?
Should I call 'retain'? (and then I would call 'release' in the receiver) Should I 'copy' the object?
I read all of the other posts about alloc, copy, new, etc.
I just need a simple example so that I can then derive understanding from it. If you can also show me an example of the receiver calling this method I would appreciate it.
Thanks!
Upvotes: 0
Views: 988
Reputation: 1283
You could use copy, but it would require that the Player
class conforms to the NSCopying
protocol, which I doubt it does.
The simplest (and probably best) way to do this here is as such:
if ([array count] == 1)
{
player = [[array objectAtIndex:0] retain];
}
[request release];
return [player autorelease];
You are keeping the player from being released for the meantime by retaining it, and then when you return it you use autorelease
. This is not strictly necessary, but I think it is good programming practice in this case. This is because your
+ (Player *)loadPlayerWithPredicate:(NSString *)name:(NSInteger)index;
function name would imply (in Obj-C standard practice) that the object returned is autoreleased, thus leaving the memory management of the object up to the caller.
In the class that you call + (Player *)loadPlayerWithPredicate:(NSString *)name:(NSInteger)index
, you will need to determine if you want to retain the returned Player (such as setting it to a retain property), or if you want to leave it as is (autoreleased, and thus will likely be released after the method this call is in has finished. Use this if you only need to perform a few actions with it immediately and don't need to hold on to it after).
Upvotes: 1