When animating the deletion of all rows and hence the deletion of all sections that included all rows of a UITableView
I am running into this error:
CRASH: attempt to delete row 2 from section 0, but there are only 0 sections before the update
In particular I have a singleton manager class that serves as the table view data source and delegate. I post an NSNotification
to tell the table view to delete rows that should be deleted, and that NSNotification
triggers the following method:
dispatch_async(dispatch_get_main_queue(), ^{
if ([[[Manager sharedManager] justDeletedIndices] count] > 0) {
[mainTableView beginUpdates];
NSMutableArray <NSIndexPath *> *pathsToDelete = [[Manager sharedManager] justDeletedIndices];
[mainTableView deleteRowsAtIndexPaths:pathsToDelete withRowAnimation:UITableViewRowAnimationFade];
[[Manager sharedManager] setJustDeletedIndices:[NSMutableArray new]];
[mainTableView endUpdates];
} else {
[mainTableView reloadData];
}
});
The code for the method is in turn triggered by a method in Manager
like so:
- (void) deleteMessagesForNotificationObjects: (NSArray <Object *> *) objects {
// this is where the property that includes the NSIndexPath
[self p_updatePathsToDeleteForDeletedObjects:objects];
// this is the notification that should trigger the code above
[[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshTableView" object:self];
// this is where I modify the underlying data structures that power
// the table view's data source
NSMutableArray *localObjects = [objects mutableCopy];
for (Object *obj in localObjects) {
[self deleteMessageWithToken:obj.token andUniqueID:nil andFireDate:obj.displayDate];
}
NSArray *allKeys = [self.displayDict allKeys];
NSMutableArray <NSString *> *keysToDelete = [NSMutableArray new];
for (NSString *key in allKeys) {
NSMutableArray <Object *> *currentArr = self.displayDict[key];
NSMutableArray <Object *> *objsToDelete = [NSMutableArray new];
for (int i = 0; i < [localObjects count]; i ++) {
if ([currentArr containsObject:localObjects[i]]) {
[objsToDelete addObject:localObjects[i]];
}
}
[currentArr removeObjectsInArray:objsToDelete];
[localObjects removeObjectsInArray:objsToDelete];
if ([currentArr count] < 1) {
[keysToDelete addObject:key];
}
}
[self.displayDict removeObjectsForKeys:keysToDelete];
self.keyOrder = [[[self class] orderedKeysFromDict:self.displayDict] mutableCopy];
}
I am unclear as to what has to happen in what order. How do the commands indicating to a table view that it has to delete certain rows in an animated fashion (discussed here: Add/Delete UITableViewCell with animation?) relate to the ordering of actually modifying the underlying data source? In what order do I (1) animate row deletion and section deletion and (2) actually delete those rows and sections?