AggiornamentoUITableView: l'eliminazione di sezioni con animazione
mi hanno inviato la mia soluzione a questo problema come una risposta di seguito. Ci vuole un approccio diverso dalla mia prima revisione.
domanda originale Ho già fatto una domanda sul SO che ho pensato risolto i miei problemi:
How to deal with non-visible rows during row deletion. (UITableViews)
Tuttavia, ora ho di nuovo problemi simili durante la rimozione di sezioni da un UITableView. (sono riemersi quando ho variato il numero di sezioni/righe nella tabella).
Prima di perderti a causa della lunghezza di taglio del mio post, permettimi di indicare chiaramente il problema e puoi leggere tutto il tempo necessario per fornire una risposta.
Problema:
Se lotti eliminazione di righe e sezioni da un UITableView, l'applicazione si blocca, a volte. Dipende dalla configurazione della tabella e dalla combinazione di righe e sezioni che scelgo di rimuovere.
Il registro dice sono caduto perché dice che non ho aggiornato l'origine dati e la tabella correttamente:
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).
Ora in fretta, prima di scrivere la risposta ovvia, vi assicuro che ho davvero aggiunto e cancellato il righe e sezioni correttamente da dataSource. La spiegazione è lunga, ma la troverai sotto, seguendo il metodo.
Quindi, con questo, se siete ancora interessati ...
metodo che gestisce la rimozione delle sezioni e righe:
- (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;
}
mia ipotesi:
Il problema Questo sembra essere questo: se guardi sopra dove elencho il numero di celle in ogni sezione, vedrai che la sezione 5 sembra aumentare di 1. Tuttavia, questo non è vero. La sezione originale 5 è stata effettivamente cancellata e un'altra sezione ha preso il suo posto (in particolare, è la vecchia sezione 10).
Quindi perché la vista del tavolo sembra non rendersene conto? È necessario SAPERE che ho rimosso la vecchia sezione e non dovremmo aspettarci che una nuova sezione che ora si trova nell'indice della vecchia sezione sia vincolata dal numero di righe della sezione eliminata.
Speriamo che questo abbia senso, è un po 'complicato scrivere questo.
(notare questo codice ha funzionato prima con un diverso numero di righe/sezioni.questa particolare configurazione sembra dargli problemi)
In alternativa, tenere traccia di IndexPath per ogni cella di cui si ha bisogno e correggerli in modo appropriato man mano che si eliminano le eliminazioni. (Questo potrebbe essere il modo lungo/contorto/inappropriato di farlo - solo un pensiero.) – Tim
Sto facendo un batch di eliminazione, quindi non fa differenza nell'ordine in cui elenco le operazioni. La vista tabella esegue le operazioni "alla volta" quando si trovano all'interno del blocco di aggiornamento. Come ero paranoico, ho provato a cambiare l'ordine delle operazioni senza successo. La numerazione delle sezioni/righe non cambia (non deve cambiare) durante l'eliminazione del batch. Se non stavi usando i blocchi, avresti ragione. –
@Tim Pensiero interessante. Hai ragione, potrebbe essere piuttosto noioso con una grande quantità di cancellazioni (che avrò). Mi chiedo anche se potrei fare più eliminazioni in rapida successione. Stavo cercando di fare eliminazioni in batch per evitare questi problemi, ma potrebbe essere necessario. –