Update
我已将我对此问题的解决方案作为答案发布在下面。它采用了与我的第一次修订不同的方法。
原始问题我之前问过一个问题,我认为解决了我的问题:
删除行时如何处理不可见行。 (UITableViews) https://stackoverflow.com/questions/998603/how-to-deal-with-non-visible-rows-during-row-deletion-uitableviews
但是,当我从 UITableView 中删除部分时,我现在再次遇到类似的问题。
(当我改变表中的部分/行数时,它们重新出现)。
在我因为帖子的长度而失去您之前,让我清楚地说明问题,您可以根据需要阅读以提供答案。
Problem:
如果从 UITableView 批量删除行和部分,应用程序有时会崩溃。这取决于表的配置以及我选择删除的行和部分的组合。
日志说我崩溃了,因为它说我没有正确更新数据源和表:
Invalid update: invalid number of rows in section 5. The number of rows contained in an existing section after the update (2) must be equal to the number of rows contained in that section before the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 0 deleted).
现在,在您写出明显的答案之前,我向您保证我确实已从数据源中正确添加和删除了行和部分。解释很长,但是您可以按照下面的方法找到它。
因此,如果您仍然感兴趣……
处理删除部分和行的方法:
- (void)createFilteredTableGroups{
//index set to hold sections to remove for deletion animation
NSMutableIndexSet *sectionsToDelete = [NSMutableIndexSet indexSet];
[sectionsToDelete removeIndex:0];
//array to track cells for deletion animation
NSMutableArray *cellsToDelete = [NSMutableArray array];
//array to track controllers to delete from presentation model
NSMutableArray *controllersToDelete = [NSMutableArray array];
//for each section
for(NSUInteger i=0; i<[tableGroups count];i++){
NSMutableArray *section = [tableGroups objectAtIndex:i];
//controllers to remove
NSMutableIndexSet *controllersToDeleteInCurrentSection = [NSMutableIndexSet indexSet];
[controllersToDeleteInCurrentSection removeIndex:0];
NSUInteger indexOfController = 0;
//for each cell controller
for(ScheduleCellController *cellController in section){
//bool indicating whether the cell controller's cell should be removed
NSString *shouldDisplayString = (NSString*)[[cellController model] objectForKey:@"filteredDataSet"];
BOOL shouldDisplay = [shouldDisplayString boolValue];
//if it should be removed
if(!shouldDisplay){
NSIndexPath *cellPath = [self indexPathOfCellWithCellController:cellController];
//if cell is on screen, mark for animated deletion
if(cellPath!=nil)
[cellsToDelete addObject:cellPath];
//marking controller for deleting from presentation model
[controllersToDeleteInCurrentSection addIndex:indexOfController];
}
indexOfController++;
}
//if removing all items in section, add section to removed in animation
if([controllersToDeleteInCurrentSection count]==[section count])
[sectionsToDelete addIndex:i];
[controllersToDelete addObject:controllersToDeleteInCurrentSection];
}
//copy the unfiltered data so we can remove the data that we want to filter out
NSMutableArray *newHeaders = [tableHeaders mutableCopy];
NSMutableArray *newTableGroups = [[allTableGroups mutableCopy] autorelease];
//removing controllers
int i = 0;
for(NSMutableArray *section in newTableGroups){
NSIndexSet *indexesToDelete = [controllersToDelete objectAtIndex:i];
[section removeObjectsAtIndexes:indexesToDelete];
i++;
}
//removing empty sections and cooresponding headers
[newHeaders removeObjectsAtIndexes:sectionsToDelete];
[newTableGroups removeObjectsAtIndexes:sectionsToDelete];
//update headers
[tableHeaders release];
tableHeaders = newHeaders;
//storing filtered table groups
self.filteredTableGroups = newTableGroups;
//filtering animation and presentation model update
[self.tableView beginUpdates];
tableGroups = self.filteredTableGroups;
[self.tableView deleteSections:sectionsToDelete withRowAnimation:UITableViewRowAnimationTop];
[self.tableView deleteRowsAtIndexPaths:cellsToDelete withRowAnimation:UITableViewRowAnimationTop];
[self.tableView endUpdates];
//marking table as filtered
self.tableIsFiltered = YES;
}
我猜:
问题似乎是这样的:如果您查看上面我列出的每个部分中的单元格数量,您会发现第 5 部分似乎增加了 1。然而,事实并非如此。原来的第 5 节实际上已被删除,并由另一个节取代(具体来说,它是旧的第 10 节)。
那么为什么表视图似乎没有意识到这一点呢?它应该知道我删除了旧的部分and不应期望现在位于旧节索引处的新节受到已删除节的行数的限制。
希望这是有道理的,写出来有点复杂。
(请注意,此代码之前适用于不同数量的行/部分。这个特定的配置似乎给它带来了问题)