actualizaciónUITableView: la supresión de secciones con animación
He publicado mi solución a este problema como una respuesta a continuación. Toma un enfoque diferente de mi primera revisión.
pregunta original anteriormente he hecho una pregunta sobre el SO que pensé resuelto mis problemas:
How to deal with non-visible rows during row deletion. (UITableViews)
Sin embargo, ahora tienen problemas similares de nuevo cuando la eliminación de secciones de un UITableView. (resurgieron cuando cambié el número de secciones/filas en la tabla).
Antes de perderlo debido a la longitud de corte de mi publicación, permítame exponer el problema con claridad, y puede leer todo lo que necesite para dar una respuesta.
Problema:
Si lote eliminar filas y secciones de un UITableView, la aplicación se bloquea, a veces. Depende de la configuración de la tabla y la combinación de filas y secciones que elijo eliminar.
El registro dice que me he caído porque dice que no he actualizado el origen de datos y la tabla correctamente:
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).
Ahora con rapidez, antes de escribir la respuesta obvia, les aseguro que he añadido de hecho y eliminado el filas y secciones correctamente desde dataSource. La explicación es larga, pero la encontrará más abajo, siguiendo el método.
Así que con eso, si usted todavía está interesado ...
método que controla la eliminación de secciones y filas:
- (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;
}
Mi suposición:
El probl em parece ser este: si miras arriba donde enumero la cantidad de celdas en cada sección, verás que la sección 5 parece aumentar en 1. Sin embargo, esto no es cierto. La sección original 5 se ha eliminado y otra sección ha ocupado su lugar (específicamente, es la antigua sección 10).
¿Por qué la vista de tabla parece no darse cuenta de esto? Debe SABER que eliminé la sección anterior y no debería esperar que una nueva sección que ahora se encuentra en el índice de la sección anterior se vincule con el número de filas de la sección eliminada.
Esperemos que esto tenga sentido, es un poco complicado escribir esto.
(tenga en cuenta que este código funcionaba antes con un número diferente de filas/secciones.esta configuración particular parece darle problemas)
De forma alternativa, realice un seguimiento de indexPath para cada celda que necesita eliminar, y ajústelas adecuadamente a medida que vaya borrando sus datos. (Esta podría ser la forma larga/intrincada/inapropiada de hacerlo, solo un pensamiento.) – Tim
Estoy haciendo una eliminación por lotes, por lo que no hace ninguna diferencia en el orden de las operaciones de la lista. La vista de tabla realiza operaciones "a la vez" cuando están dentro del bloque de actualización. Como estaba paranoico, intenté cambiar el orden de las operaciones en vano. La numeración de las secciones/filas no cambia (no debe cambiar) durante la eliminación del lote. Si no estuvieras usando los bloques, estarías en lo correcto. –
@Tim Interesante pensamiento. Tienes razón, eso podría ser bastante tedioso con una gran cantidad de eliminaciones (que tendré). También me pregunto si podría hacer varias eliminaciones en rápida sucesión. Estaba tratando de eliminar lotes para evitar estos problemas, pero puede ser necesario. –