UITableView: удаление разделов с анимацией

Update

Я разместил свое решение этой проблемы в качестве ответа ниже. Это отличается от моего первого пересмотра.

Original Question Ранее я задавал вопрос о SO, который, как я думал, решил мои проблемы:

Как бороться с невидимыми строками во время удаления строк. (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).

Теперь быстро, прежде чем написать очевидный ответ, уверяю вас, я действительно добавил и удалил строки и разделы должным образом из источника данных. Объяснение длинное, но вы найдете его ниже, следуя методу.

Так что, если вы все еще заинтересованы, & # x2026;

Method that handles removal of sections and rows:

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


}

My guess:

Кажется, проблема заключается в следующем: если вы посмотрите выше, где я перечисляю количество ячеек в каждом разделе, вы увидите, что раздел 5 кажется увеличенным на 1. Однако это не так. Первоначальный раздел 5 был фактически удален, и его место занял другой раздел (в частности, это старый раздел 10).

Так почему табличное представление не осознает этого? Стоит ЗНАТЬ, что я удалил старый разделand не следует ожидать, что новый раздел, который теперь расположен по индексу старого раздела, будет связан количеством строк в удаленном разделе.

Надеюсь, это имеет смысл, это немного сложно записать.

(обратите внимание, что этот код работал раньше с другим количеством строк / разделов. Эта конкретная конфигурация, кажется, создает проблемы)

Ответы на вопрос(7)

Ваш ответ на вопрос