Reputation: 4577
My guess is I'm missing some Core Data fundamental understanding here, but here goes:
I have several fetch requests in my app to handle retrieval of different things. In some cases the code runs fine, returning the requested objects.
In some cases, it returns what appear to be already-released objects (e.g. just a few lines of code later trying to reference the returned result gives EXC_BAD_ACCESS). As I set various breakpoints and log statements in the code and step through it will also get the occasional SIGABRT or EXC_BAD_ACCESS in other locations in the code.
In every case, it appears to be when I go to reference the result of a fetch request.
Here's a sample of one such fetch request:
// Who am I?
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *signedInPersonId = [defaults stringForKey:@"signedInPersonId"];
// Return (if any) the Request object with given UUID
RequestStrings *r = [[RequestStrings alloc] init];
NSEntityDescription *description = [NSEntityDescription entityForName:r.table_Request inManagedObjectContext:moc];
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(UUID == %@) && (dataOwnerId == %@)", UUID, signedInPersonId];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:description];
[request setPredicate:predicate];
NSError *error = nil;
NSArray *requests = [moc executeFetchRequest:request error:&error];
Request *returnRequest = nil;
if (requests != nil) {
if ([requests count] > 0) {
NSLog(@"getRequestWithId - requests array: %@, first: %@", requests, [requests objectAtIndex:0]);
returnRequest = [requests objectAtIndex:0];
}
else {
returnRequest = nil;
}
}
[r release];
[request release];
return returnRequest;
P.S. Here's some more info
In some instances the same code will return the desired objects, or throw an exception stating that [NSCFNumber length]
is an unrecognized selector. Not sure how the same entity description + fetch request could return an array in one case and a Number in the other.
Upvotes: 3
Views: 3885
Reputation: 4577
@deanWombourne - good suggestions, and I think you're right on. It turns out I actually was crashing from a zombie (wasn't using my own setters in a previous view controller when I was using values from a previously fetched managed object).
The solution: EXC_BAD_ACCESS is always worth a trip down zombie lane. Do your due diligence on memory management.
Upvotes: 0
Reputation: 38475
You're basically doing this :
// (1) Create an array of stuff
NSArray *myArray = [NSarray arrayWithObjects:a, b, c, nil];
// (2) Take the first one off
id myObject = [myArray objectAtIndex:0];
// (3) Release everything
[myArray release];
// (4) Return myObject
return myObject;
You're just using CoreData to do step (1).
Step (1) returns an array of objects. The only thing retaining these objects is the array that they're in*. If you release the array (step 3), you will release all the objects that are inside it. Why do you expect myObject to still exist by step (4)?
Try this :
// Make sure that we keep a retain of returnRequest
returnRequest = [[[requests objectAtIndex:0] retain] autorelease];
*For the pedantic out there : I've made an assumption that makes my answer simpler. In the real world you don't know what's retaining your objects - that's up to the framework as well as your code. However, it's good practice to retain anything you expect to keep around.
Upvotes: 4
Reputation: 23268
Why don't you do all the releases at the end before the return? This should fix your issue as you're releasing things immediately after creating them.
Upvotes: 0