UITableView: usuwanie sekcji z animacją

Aktualizacja

Opublikowałem moje rozwiązanie tego problemu jako odpowiedź poniżej. To wymaga innego podejścia niż moja pierwsza wersja.

Pytanie oryginalne Wcześniej zadałem pytanie na temat SO, które myślałem, że rozwiązało moje problemy:

Jak radzić sobie z niewidocznymi wierszami podczas usuwania wiersza. (UITableViews)

Jednak teraz mam podobne problemy podczas usuwania sekcji z UITableView. (pojawili się ponownie, gdy zmieniłem liczbę sekcji / wierszy w tabeli).

Zanim stracę cię z powodu długości ścinania mojego posta, pozwól mi jasno przedstawić problem i możesz przeczytać tyle, ile potrzebujesz, aby udzielić odpowiedzi.

Problem:

Jeśli partia usuwająca wiersze i sekcje z UITableView, aplikacja czasami ulega awarii. Zależy to od konfiguracji tabeli i kombinacji wierszy i sekcji, które wybieram do usunięcia.

Dziennik mówi, że się zawiesiłem, ponieważ mówi, że nie zaktualizowałem źródła danych i tabeli poprawnie:

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).

Teraz szybko, zanim napiszesz oczywistą odpowiedź, zapewniam cię, że rzeczywiście dodałem i usunąłem wiersze i sekcje poprawnie ze źródła danych. Wyjaśnienie jest długie, ale znajdziesz je poniżej, zgodnie z metodą.

Tak więc, jeśli nadal jesteś zainteresowany…

Metoda, która obsługuje usuwanie sekcji i wierszy:

- (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; 


}

Zgaduję że:

Problem wydaje się być następujący: Jeśli spojrzysz powyżej, gdzie wymieniam liczbę komórek w każdej sekcji, zobaczysz, że sekcja 5 wydaje się zwiększać o 1. Jednak nie jest to prawdą. Oryginalna sekcja 5 została faktycznie usunięta, a jej miejsce zajęła inna sekcja (konkretnie jest to stara sekcja 10).

Dlaczego więc widok tabeli nie zdaje sobie z tego sprawy? Powinien WIEDZIEĆ, że usunąłem starą sekcjęi nie należy oczekiwać, że nowa sekcja, która znajduje się teraz w indeksie starej sekcji, będzie powiązana przez liczbę wierszy usuniętej sekcji.

Mam nadzieję, że ma to sens, trochę to komplikuje.

(zwróć uwagę, że ten kod działał wcześniej z inną liczbą wierszy / sekcji. ta konkretna konfiguracja wydaje się sprawiać problemy)

questionAnswers(7)

yourAnswerToTheQuestion