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

Я только что столкнулся с этой проблемой при настройке моего текущего проекта, и ни одно из вышеуказанных решений не работает поэтому я попытался посмотреть, что на самом деле происходит в списке отладки, используя команду ssh -vT git@github.com. Я заметил, что моего закрытого ключа с именем файла нет в списке. поэтому переименовав имя файла с закрытым ключом в id_rsa, сделайте свою работу. надеюсь, это поможет.

40
задан Community 23 May 2017 в 12:16
поделиться

3 ответа

Я уже сталкивался с этой проблемой раньше. Вы пытаетесь удалить все строки из раздела, а затем, вдобавок, этот теперь пустой раздел. Однако этого достаточно (и правильно) чтобы удалить только этот раздел. Все строки в нем также будут удалены. Вот пример кода из моего проекта, который обрабатывает удаление одной строки.Ему необходимо определить, следует ли удалить только эту строку из раздела или удалить весь раздел, если это последняя оставшаяся строка в этом разделе:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        // modelForSection is a custom model object that holds items for this section.
        [modelForSection removeItem:[self itemForRowAtIndexPath:indexPath]];

        [tableView beginUpdates];

        // Either delete some rows within a section (leaving at least one) or the entire section.
        if ([modelForSection.items count] > 0)
        {
            // Section is not yet empty, so delete only the current row.
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
        }
        else
        {
            // Section is now completely empty, so delete the entire section.
            [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] 
                     withRowAnimation:UITableViewRowAnimationFade];
        }

        [tableView endUpdates];
    }
}
88
ответ дан 27 November 2019 в 01:20
поделиться

Я заметил, что вы сначала удаляете разделы из таблицы, а затем удаляете строки.

Я знаю, что есть сложное обсуждение пакетной вставки и удаления для UITableViews в Руководстве по программированию табличного представления, но это конкретно не рассматривается.

Я думаю, что происходит то, что удаление разделов приводит к тому, что удаления строк ссылаются на неправильную строку.

т.е. вы хотите удалить раздел №2 и строку №1 из раздела №4 ... но после того, как вы ' Если вы удалили раздел №2, старый раздел №4 теперь является третьим разделом, поэтому при удалении со старым NSIndexPath (4, 1) вы удаляете какую-то случайную другую строку, которая может не существовать.

Итак, я Думаю, что для исправления достаточно просто поменять местами эти две строки кода, поэтому сначала нужно удалить строки, а затем разделы.

4
ответ дан 27 November 2019 в 01:20
поделиться

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

Как и прежде, я модифицировал код табличного представления Мэтта Галлахера, который помещает логику, специфичную для ячейки, в отдельный контроллер ячейки. Однако вы можете легко адаптировать этот метод к другой модели

Я добавил следующие (соответствующие) ivar в код Мэтта:

NSArray *allTableGroups; //always has a copy of every cell controller, even if filtered
NSArray *filteredTableGroups; //always has a copy of the filtered table groups

Исходный ivar Мэтта:

NSArray *allTableGroups

... всегда указывает на один из вышеуказанных массивов.

Это, вероятно, можно реорганизовать и значительно улучшить, но в этом мне не было необходимости. Кроме того, если вы используете Core Data, NSFetchedResultsController упрощает эту задачу.

Теперь перейдем к методу (я пытаюсь прокомментировать как можно больше):

- (void)createFilteredTableGroups{

    //Checking for the usual suspects. all which may through an exception
    if(model==nil)
        return;
    if(tableGroups==nil)
        return;
    if([tableGroups count]==0)
        return;


    //lets make a new array to work with
    NSMutableArray *newTableGroups = [[allTableGroups mutableCopy] autorelease];

    //telling the table what we are about to do
    [self.tableView beginUpdates];


    //array to track cells for deletion animation
    NSMutableArray *indexesToRemove = [NSMutableArray array];

    //loop through each section
    for(NSMutableArray *eachSection in tableGroups){

        //keeping track of the indexes to delete for each section
        NSMutableIndexSet *indexesForSection = [NSMutableIndexSet indexSet];
        [indexesForSection removeAllIndexes];

        //increment though cell indexes
        int rowIndex = 0;

        //loop through each cellController in the section
        for(ScheduleCellController *eachCellController in eachSection){

            //Ah ha! A little magic. the cell controller must know if it should be displayed.
            //This you must calculate in your business logic
            if(![eachCellController shouldDisplay]){

                //add non-displayed cell indexes 
                [indexesForSection addIndex:rowIndex];

            }
            rowIndex++;   
        }
        //adding each array of section indexes, EVEN if it is empty (no indexes to delete)
        [indexesToRemove addObject:indexesForSection];

    }

    //Now we remove cell controllers in newTableGroups and cells from the table
    //Also, each subarray of newTableGroups is mutable as well
    if([indexesToRemove count]>0){

        int sectionIndex = 0;
        for(NSMutableIndexSet *eachSectionIndexes in indexesToRemove){

            //Now you know why we stuck the indexes into individual arrays, easy array method
            [[newTableGroups objectAtIndex:sectionIndex] removeObjectsAtIndexes:eachSectionIndexes];

            //tracking which cell indexPaths to remove for each section
            NSMutableArray *indexPathsToRemove = [NSMutableArray array];
            int numberOfIndexes = [eachSectionIndexes count];

            //create array of indexPaths to remove
            NSUInteger index = [eachSectionIndexes firstIndex];
            for(int i = 0; i< numberOfIndexes; i++){

                NSIndexPath *indexPath = [NSIndexPath indexPathForRow:index inSection:sectionIndex];
                [indexPathsToRemove addObject:indexPath];
                index = [eachSectionIndexes indexGreaterThanIndex:index];
            }

            //delete the rows for this section
            [self.tableView deleteRowsAtIndexPaths:indexPathsToRemove withRowAnimation:UITableViewRowAnimationTop];

            //next section please
            sectionIndex++;
        }

    }

    //now we figure out if we need to remove any sections
    NSMutableIndexSet *sectionsToRemove = [NSMutableIndexSet indexSet];
    [sectionsToRemove removeAllIndexes];

    int sectionsIndex = 0;
    for(NSArray *eachSection in newTableGroups){

        //checking for empty sections
        if([eachSection count]==0)
            [sectionsToRemove addIndex:sectionsIndex];

        sectionsIndex++;
    }

    //updating the table groups
    [newTableGroups removeObjectsAtIndexes:sectionsToRemove];

    //removing the empty sections
    [self.tableView deleteSections:sectionsToRemove withRowAnimation:UITableViewRowAnimationTop];

    //updating filteredTableGroups to the newTableGroups we just created
    self.filteredTableGroups = newTableGroups;

    //pointing tableGroups at the filteredGroups
    tableGroups = filteredTableGroups;

    //invokes the animation
    [self.tableView endUpdates];


}
3
ответ дан 27 November 2019 в 01:20
поделиться
Другие вопросы по тегам:

Похожие вопросы: