Reputation: 16715
I have a UITableView
that displays attributes of entities that are in an array
created with an NSFetchRequest
. My instructor tells me for my purposes, I do NOT need a fetchedResultsController
--so I do NOT need to add NSFetchedResultsControllerDelegate
methods to my UITableViewController
class. His analogy was putting a Porsche engine in a VW Beetle.
My tableView has 2 sections (0 and 1). Everything works fine until I try to delete objects from section 1 (section 0 is static).
With this commitEditingStyle code, the app crashes with his error:
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:],
/SourceCache/UIKit_Sim/UIKit-3347.40/UITableView.m:1623
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete && indexPath.section == 1) {
// Delete cell
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
// Delete LocationCategory from managedObjectContext
LocationCategory *categoryToDelete = [self.locationCategories objectAtIndex:indexPath.row];
[self.managedObjectContext deleteObject:categoryToDelete];
[self.managedObjectContext save:nil];
} 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
}
}
When I restart the app, the locationCategory
(my NSManagedObject
) is no longer in the managedObjectContext
. I know I've got a problem updating the tableView
, but I don't know how to resolve it. I've dug around, tried a bunch of prospective solutions, but nothing resolves the crashing.
Here's how my array is created:
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
self.title = @"Select a Category";
// Core Data
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication]delegate];
self.managedObjectContext = [appDelegate managedObjectContext];
// Fetch LocationCategories & dump them in an array
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntityDescription entityForName:@"LocationCategory" inManagedObjectContext:self.managedObjectContext]];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"categoryName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:&sortDescriptor count:1];
[fetchRequest setSortDescriptors:sortDescriptors];
NSArray *categories = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
self.locationCategories = categories;
[self.tableView reloadData];
}
Update:
Here's what the code looked like at the end when it worked:
// This was previously an NSArray. It needs to be an NSMutableArray
@property (nonatomic, strong) NSMutableArray *locationCategories;
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
if (editingStyle == UITableViewCellEditingStyleDelete && indexPath.section == 1) {
// Delete LocationCategory from managedObjectContext
LocationCategory *categoryToDelete = [self.locationCategories objectAtIndex:indexPath.row];
[self.managedObjectContext deleteObject:categoryToDelete];
[self.locationCategories removeObjectAtIndex:indexPath.row];
[self.managedObjectContext save:nil];
// Delete cell
[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView endUpdates];
} 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
}
}
Upvotes: 0
Views: 286
Reputation: 21536
Presumably your tableView datasource methods use self.locationCaregories
. If so, the problem is that you don't remove the relevant Category
from that array (although you delete it from the managedObjectContext, it remains in the array).
Now, because self.locationCategories
is an NSArray, it is immutable, so you can't just remove the relevant item. You could reperform the fetch immediately after you delete the object, but that seems a bit inefficient. I recommend instead that you make self.locationCategories
an NSMutableArray. You will need to amend the property definition, and also the line in viewWillAppear
where you first set it:
NSArray *categories = [self.managedObjectContext executeFetchRequest:fetchRequest error:nil];
self.locationCategories = [categories mutableCopy];
Then in the commitEditingStyle
method, you can remove the relevant object from the array:
LocationCategory *categoryToDelete = [self.locationCategories objectAtIndex:indexPath.row];
[self.locationCategories removeObjectAtIndex:indexPath.row];
And as thorb65 says, move the code to delete the rows to the end of the method - you should get the data right, before you update the table.
Upvotes: 1