views:

110

answers:

1

To preface, this is a follow up to an inquiry made a few days ago: http://stackoverflow.com/questions/2981803/iphone-app-crashes-when-merging-managed-object-contexts

Short Version: EXC_BAD_ACCESS is crashing my app, and zombie-mode revealed the culprit to be my predicate embedded within the fetch request embedded in my Fetched Results Controller. How does an object within an object get released without an explicit command to do so?

Long Version: Application Structure Platforms View Controller -> Games View Controller (Predicated upon platform selection) -> Add Game View Controller

When a row gets clicked on the Platforms view, it sets an instance variable in Games View for that platform, then the Games Fetched Results Controller builds a fetch request in the normal way:

- (NSFetchedResultsController *)fetchedResultsController{
if (fetchedResultsController != nil) {
  return fetchedResultsController;
}
//build the fetch request for Games
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription 
  entityForName:@"Game"
  inManagedObjectContext:context];
[request setEntity:entity];
//predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:@"platform == %@",
  selectedPlatform];
[request setPredicate:predicate];
//sort based on name
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"name"
  ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:sortDescriptor, nil];
[request setSortDescriptors:sortDescriptors];

//fetch and build fetched results controller
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] 
  initWithFetchRequest:request 
  managedObjectContext:context 
  sectionNameKeyPath:nil 
  cacheName:@"Root"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;

[sortDescriptor release];
[sortDescriptors release];
[predicate release];
[request release];
[aFetchedResultsController release];

return fetchedResultsController;
} 

At the end of this method, the fetchedResultsController's _fetch_request -> _predicate member is set to an NSComparisonPredicate object. All is well in the world.

By the time - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section gets called, the _predicate is now a Zombie, which will eventually crash the application when the table attempts to update itself.

I'm more or less flummoxed. I'm not releasing the fetched results controller or any of it's parts, and the only part getting dealloc'd is the predicate. Any ideas?

EDIT: As a test, I added this line to the Fetched Results Controller method:

[fetchedResultsController.fetchRequest.predicate retain];

And now it doesn't crash, but that seems like a patch, not something I should be doing.

+7  A: 

You shouldn't be releasing your predicate variable. You didn't invoke new, alloc, retain, or copy (This is the "narc" rule) to create the predicate, so you are not responsible for releasing it. That's where your zombie is coming from.

Dave DeLong
Thanks. I feel silly now :)
DVG
You should mark this as the right answer to increase your rep and to flag this question as answered.
Marcus S. Zarra