Although I have worked with NSFetchedResultsController dozens of times, I ran into a problem, I can not find the reason.
I have a UIViewController with an NSFetchedResultsController that controls a data source in a table. Whenever I delete an object in the NSFetchedResultsController , the table view is updated using the selected result controller, but when I save the NSManagedObjectContext (to fix the deletion), the insert starts in the object that was just deleted. The end result is that the object is not removed from the table view.
The strange thing is that when you restart the application, the object that was supposed to be deleted is actually deleted from the repository and does not appear in the form of a table.
To be clear, I use only one managed entity context, accessed only in the main thread. In other words, the setup is pretty simple.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath { if (editingStyle == UITableViewCellEditingStyleDelete) { // Fetch Store CCDStore *store = [self.fetchedResultsController objectAtIndexPath:indexPath]; // Delete Store [self.fetchedResultsController.managedObjectContext deleteObject:store]; // Save Changes NSError *error = nil; [self.fetchedResultsController.managedObjectContext save:&error]; if (error) { NSLog(@"Error %@ with user info %@.", error, error.userInfo); } } }
Despite the fact that the deleted object is inserted into the selected result controller, the object turns into an error, but I do not understand why it was added to the selected result controller in the first place.
No exceptions or errors are thrown. I performed several checks such as calling the isDeleted and validateForDelete object to find the reason, but I did not become wiser.
EDIT:
I am pretty sure that the delegate methods of the result manager selected are not the culprits, but for completeness, I added the implementation of controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath { [self updateView]; switch(type) { case NSFetchedResultsChangeInsert: { [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeDelete: { [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; break; } case NSFetchedResultsChangeUpdate: { [self configureCell:(CCDStoreCell *)[self.tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath]; break; } case NSFetchedResultsChangeMove: { [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade]; [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]withRowAnimation:UITableViewRowAnimationFade]; break; } default: { break; } } }