UITableView: borrando secciones con animación.

Actualizar

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 hice una pregunta sobre SO que pensé que resolvía mis problemas:

Cómo tratar con las filas no visibles durante la eliminación de la fila. (UITableViews)

Sin embargo, ahora vuelvo a tener problemas similares cuando elimino secciones de un UITableView. (resurgieron cuando varié el número de secciones / filas en la tabla).

Antes de perderte debido a la longitud de corte de mi publicación, permíteme plantear el problema con claridad, y puedes leer todo lo que necesites para dar una respuesta.

Problema:

Si se eliminan por lotes filas Y secciones de un UITableView, la aplicación falla, 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 bloqueé porque dice que no he actualizado la fuente 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, rápidamente, antes de que escriba la respuesta obvia, le aseguro que he agregado y eliminado las filas y secciones correctamente de la fuente de datos. La explicación es larga, pero la encontrarás a continuación, siguiendo el método.

Así que con eso, si todavía estás interesado ...

Método que maneja 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 conjetura:

El problema parece ser el siguiente: si mira arriba, donde enumero la cantidad de celdas en cada sección, verá que la sección 5 parece aumentar en 1. Sin embargo, esto no es cierto. La sección 5 original se ha eliminado y otra sección ha tomado su lugar (específicamente, es la sección 10 anterior).

Entonces, ¿por qué la vista de tabla parece no darse cuenta de esto? Debería SABER que quité la vieja seccióny no debe esperar que una nueva sección que ahora se encuentra en el índice de la sección anterior esté limitada por 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 funcionó antes con un número diferente de filas / secciones. Esta configuración particular parece darle problemas)

Respuestas a la pregunta(7)

Su respuesta a la pregunta