Core Data application crashes with "controllerWillChangeContent: unrecognized selector sent to instance"

I have an application with basic data with 2 views. The first view lists the "Rooms", the second - "Scenes" in the rooms. There is a NavItem edit button on the Rooms page, which, when clicked, allows you to add a NavItem button. You can delete and add numbers from here. Added rooms simply appear with the name "New Room" by default in the table. The second view is a list of scenes in the selected room. Here you can delete and add scenes, and added scenes simply appear in the table with the name "New Scene". Nothing special.

I use FetchedResultsController in both view controllers, and in Scenes that has NSPredicate , only scenes from the selected room are returned. I also use the delegate methods controllerWillChangeContent , controllerDidChangeContent , etc. For table view updates.

At first, everything works fine, but usually after navigating through rooms and scenes, and then trying to delete a scene, it will work. This will inevitably fail if you play with it long enough. This only happens when a scene is deleted. If you press the edit button and delete the scene, and it will work, then all subsequent deletions in this editing session will always work. This will only happen the first time you delete an editing session.

The error I get is strange:

Application termination due to an uncaught exception 'NSInvalidArgumentException', reason: '- [__ NSCFType controllerWillChangeContent:]: unrecognized selector sent to instance 0x5e02d70

The first part of this error sometimes changes. Sometimes it is __NSCFType , sometimes it is CALayer . This error occurs only when deleting episodes. Adding scenes is a 100% penalty.

I read another post about stackoverflow, which suggests that such errors may occur due to memory management issues. I double-checked the code, and also ran it using tools with a leak tool. No leaks.

Is there anything else I can check? Any ideas?

Here is the corresponding code ..

From ScenesTableViewController.m:

 // used to show/hide the add button - (void)setEditing:(BOOL)editing animated:(BOOL)animate { [super setEditing:editing animated:animate]; if(editing) { self.navigationItem.leftBarButtonItem = addButton; } else { self.navigationItem.leftBarButtonItem = nil; } } // called when the add button is pressed - (void)addAction { NSEntityDescription *myContentEntity = [NSEntityDescription entityForName:@"Scene" inManagedObjectContext:managedObjectContext]; Scene *contentToSave = [[Scene alloc] initWithEntity:myContentEntity insertIntoManagedObjectContext:managedObjectContext]; [contentToSave setValue:@"New Scene" forKey:@"Name"]; [parentRoom addRoomToScenesObject:contentToSave]; NSError *error; if (![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); } [contentToSave release]; } // delegate method that being sent unrecognised selectors - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller { // The fetch controller is about to start sending change notifications, so prepare the table view for updates. [self.tableView beginUpdates]; } // cell display code - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; UITableViewCell *cell = nil; cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (!cell) { cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease]; [cell setAccessoryType:UITableViewCellAccessoryDisclosureIndicator]; } [self configureCell:cell atIndexPath:indexPath]; return cell; } - (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath { NSManagedObject *mo = nil; NSString *temp = nil; mo = [fetchedResultsController objectAtIndexPath:indexPath]; temp = [mo valueForKey:@"Name"]; [[cell textLabel] setText:temp]; } // cell editing code - (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Delete the managed object at the given index path. [managedObjectContext deleteObject:[fetchedResultsController objectAtIndexPath:indexPath]]; NSError *error; if (![managedObjectContext save:&error]) { // Update to handle the error appropriately. NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); // Fail } } else if (editingStyle == UITableViewCellEditingStyleInsert) { // Create a new instance of the appropriate class, insert it into the array, and add a new row to the table view } } // NSFetchedResultsController code - (NSFetchedResultsController *)fetchedResultsController { if (fetchedResultsController != nil) { return fetchedResultsController; } /* Set up the fetched results controller. */ // Create the fetch request for the entity. NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init]; // Edit the entity name as appropriate. NSEntityDescription *entity = [NSEntityDescription entityForName:@"Scene" inManagedObjectContext:managedObjectContext]; NSSortDescriptor *nameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"Name" ascending:YES]; NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:nameDescriptor, nil]; NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(SceneToRoom == %@)", parentRoom]; [fetchRequest setSortDescriptors:sortDescriptors]; [fetchRequest setPredicate:predicate]; [fetchRequest setEntity:entity]; // Edit the section name key path and cache name if appropriate. // nil for section name key path means "no sections". NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:nil cacheName:nil]; aFetchedResultsController.delegate = self; self.fetchedResultsController = aFetchedResultsController; [aFetchedResultsController release]; [fetchRequest release]; [nameDescriptor release]; [sortDescriptors release]; return fetchedResultsController; } 
+7
ios iphone core-data nsfetchedresultscontroller
source share
2 answers

This error most likely comes from NSFetchedResultsController , which has a dedicated delegate. Do you have a UIViewController that you have released and not released the associated NSFetchedResultsController ?

+28
source share

Even I ran into the same problem. But for iOS 4.2, the problem is initialized by NSError , so it is treated as garbage, and when updating / pasting we have

 if (![managedObjectContext save:&error]) { NSLog(@"Unresolved error %@, %@", error, [error userInfo]); exit(-1); } 

Thus, when saved, iOS treats the error as garbage and, therefore, an exception. Try to initialize it to zero. This solved my problem. The problem is visible only with 4.2iOS.

+1
source share

All Articles