iOS – удаление строки из UITableView не анимируется

У меня очень неприятная проблема. У меня есть приложение с UITableView. Когда я удаляю ячейку из представления таблицы, она удаляется из модели данных, а затем я вызываю следующее:

-(void)removeItem:(NSIndexPath *)indexPath {
    [self.tableView beginUpdates];

    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                      withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}

Моя проблема в том, что я пробовал это, как и выше, и я пробовал без использования animateWithDuration. Я даже пытался использовать CATransaction, но как бы я это ни делал, анимация не происходит.

У меня в симуляторе медленная анимация, и когда я удаляю элемент из списка, он удаляется правильно, но без анимации. Он просто исчезает и оставляет пустое место на мгновение, прежде чем данные табличного представления перезагрузятся.

Я искал по всему SO и Google, и я не могу найти ответ. Любые идеи?

Возможно, это связано с тем, что я удаляю объект из модели данных перед вызовом функции выше?

Редактировать: удален блок анимации, так как он некорректен


person Daniel Retief Fourie    schedule 20.08.2013    source источник
comment
Попробуйте удалить все это из блока animateWithDuration:animations:. Табличное представление обрабатывает анимацию самостоятельно, вам не нужно ничего делать.   -  person IluTov    schedule 20.08.2013
comment
Покажите свой commitEditingStyle: метод, пожалуйста   -  person Valentin Shamardin    schedule 20.08.2013
comment
Спасибо всем, но, как я сказал в вопросе, я пробовал и без animateWithDuration:animations:, и это не решает проблему. @Валентин: Скоро покажу.   -  person Daniel Retief Fourie    schedule 20.08.2013
comment
Я довольно новичок в этой части кода и iOS в целом. Я вижу, что мы не реализуем метод commitEditingStyle:. Фактическое удаление из модели данных происходит в блоке удаления внутри вызова RESTKit, если это имеет значение.   -  person Daniel Retief Fourie    schedule 20.08.2013
comment
Я бы предложил отредактировать блок анимации из вашего вопроса, потому что это просто неправильно. В противном случае код, которым вы поделились, выглядит правильно. Но вы на самом деле мало чем поделились. Мне интересно, что еще вы делаете, что может прервать анимацию. Вы сказали, что перед перезагрузкой данных табличного представления. Я не знаю, что ты имеешь в виду. Вы звоните reloadData не потому, что это может нарушить анимацию?   -  person Timothy Moose    schedule 21.08.2013
comment
Спасибо, Тимоти, я отредактирую блок анимации. Я имею в виду, что данные табличного представления перезагружаются, так это то, что ячейка сразу же удаляется, оставляя пустое место, прямо перед тем, как другие элементы, расположенные ниже, скользят вверх, чтобы заполнить пустое пространство.   -  person Daniel Retief Fourie    schedule 21.08.2013


Ответы (4)


Согласно ЭТОМУ вам вообще не нужно использовать animateWithDuration:animations:.

Просто попробуй вот так

-(void)removeItem:(NSIndexPath *)indexPath {
    [self.tableView beginUpdates];
    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                  withRowAnimation:UITableViewRowAnimationRight];
    [self.tableView endUpdates];
}
person IluTov    schedule 20.08.2013
comment
Спасибо всем, но, как я сказал в вопросе, я пробовал и без animateWithDuration:animations:, и это не решает проблему. - person Daniel Retief Fourie; 20.08.2013

Хорошо, я не знаю, может это просто плохие манеры, но я чувствую, что собираюсь ответить на свой вопрос здесь.

Во-первых, спасибо за все остальные ответы, вы все, конечно, были правы, но ни один из ответов не решил мою проблему.

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

Итак, ответ следующий:

Когда вы удаляете строку, но анимация не работает, убедитесь, что вы не вызываете didSelectRowAtIndexPath:indexPath до запуска анимации. Это отменит анимацию.


Если у вас НЕ возникла эта проблема, вот действительно типичный код для расширения, две строки в примере:

Обратите внимание, что facebookRowsExpanded — это переменная класса, которую вы должны иметь:

if ( [theCommand isEqualToString:@"fbexpander"] )
{
NSLog(@"expander button......");
[tableView deselectRowAtIndexPath:indexPath animated:NO];

NSArray *deleteIndexPaths;
NSArray *insertIndexPaths;

facebookRowsExpanded = !facebookRowsExpanded;
// you must do that BEFORE, not AFTER the animation:

if ( !facebookRowsExpanded ) // ie, it was just true, is now false
    {
    deleteIndexPaths = [NSArray arrayWithObjects:
            [NSIndexPath indexPathForRow:2 inSection:0],
            [NSIndexPath indexPathForRow:3 inSection:0],
             nil];
    [tableView beginUpdates];
    [tableView
        deleteRowsAtIndexPaths:deleteIndexPaths
        withRowAnimation: UITableViewRowAnimationMiddle];
    [tableView endUpdates];
    }
else
    {
    insertIndexPaths = [NSArray arrayWithObjects:
            [NSIndexPath indexPathForRow:2 inSection:0],
            [NSIndexPath indexPathForRow:3 inSection:0],
             nil];
    [tableView beginUpdates];
    [tableView
        insertRowsAtIndexPaths:insertIndexPaths
        withRowAnimation: UITableViewRowAnimationMiddle];
    [tableView endUpdates];
    }

// DO NOT do this at the end: [_superTableView reloadData];
return;
}

ПРИМЕЧАНИЕ: ваш код для numberOfRowsInSection должен использовать facebookRowsExpanded.

(это будет что-то вроде «если facebookRowsExpanded вернет 7, иначе вернет 5»)

ПРИМЕЧАНИЕ: ваш код для cellForRowAtIndexPath должен использовать facebookRowsExpanded.

(он должен вернуть правильную строку, в зависимости от того, расширены вы или нет.)

person Daniel Retief Fourie    schedule 21.08.2013
comment
Сегодня у меня была такая же проблема, и в моем случае оказалось, что вызов метода reloadData отменяет анимацию. Удалив метод reloadData, вы вернули анимацию, которую, как я вижу, вы также написали в комментарии в конце своего кода. - person Philip Borges; 16.04.2014

Во-первых, вам не нужно анимировать изменение самостоятельно.

Во-вторых, я думаю, вам нужно внести изменения в источник данных между начальным и конечным обновлениями.

Ваш метод должен выглядеть примерно так:

-(void)removeItemAtIndexPath:(NSIndexPath *)indexPath{

    [self.tableView beginUpdates];

    // I am assuming that you're just using a plain NSMutableArray to drive the data on the table.

    // Delete the object from the datasource.
    [self.dataArray removeObjectAtIndex:indexPath.row];

    // Tell the table what has changed.
    [self.tableView deleteRowsAtIndexPaths:@[indexPath]
                  withRowAnimation:UITableViewRowAnimationRight];

    [self.tableView endUpdates];
}
person Fogmeister    schedule 20.08.2013
comment
Я посмотрю, возможно ли это. Удаление из модели данных сложное и происходит совсем в другом месте, внутри блока, связанного с вызовом RESTKit. Я попробую и посмотрю, возможно ли это. Я просто не знаю, в этом ли дело. Так как удаление из tableview работает на 100%, просто не анимируется. - person Daniel Retief Fourie; 20.08.2013

[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView deleteRowsAtIndexPaths:indexPaths withRowAnimation:UITableViewRowAnimationFade];
[self.tableView endUpdates];

indexPaths — это массив NSIndexPath, который нужно вставить или удалить в вашей таблице.

 NSarray *indexPaths = [[NSArray alloc] initWithObjects:
    [NSIndexPath indexPathForRow:0 inSection:0],
    [NSIndexPath indexPathForRow:1 inSection:0],
    [NSIndexPath indexPathForRow:2 inSection:0],
    nil];
person Kunal Gupta    schedule 02.02.2016