Как определить, что анимация закончилась на UITableView beginUpdates/endUpdates?
Я вставляю/удаляю ячейку таблицы, используя insertRowsAtIndexPaths/deleteRowsAtIndexPaths
, завернутый в beginUpdates/endUpdates
. Я также использую beginUpdates/endUpdates
при настройке rowHeight. Все эти операции анимируются по умолчанию.
Как я могу обнаружить, что анимация закончилась при использовании beginUpdates/endUpdates
?
Ответы
Ответ 1
Как насчет этого?
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// animation has finished
}];
[tableView beginUpdates];
// do some work
[tableView endUpdates];
[CATransaction commit];
Это работает, потому что анимация tableView использует анимацию CALayer
внутри. То есть, они добавляют анимации к любому открытому CATransaction
. Если нет открытого CATransaction
(нормального случая), то он неявно начинается, который заканчивается в конце текущей runloop. Но если вы начинаете сами, как это делается здесь, тогда он будет использовать этот.
Ответ 2
Быстрая версия
CATransaction.begin()
CATransaction.setCompletionBlock({
do.something()
})
tableView.beginUpdates()
tableView.endUpdates()
CATransaction.commit()
Ответ 3
Возможное решение может заключаться в наследовании от UITableView, на котором вы вызываете endUpdates
, и перезаписывать его setContentSizeMethod
, поскольку UITableView корректирует свой размер содержимого в соответствии с добавленными или удаленными строками. Этот подход также должен работать для reloadData
.
Чтобы гарантировать, что уведомление отправлено только после вызова endUpdates
, можно также перезаписать endUpdates
и установить там флаг.
// somewhere in header
@private BOOL endUpdatesWasCalled_;
-------------------
// in implementation file
- (void)endUpdates {
[super endUpdates];
endUpdatesWasCalled_ = YES;
}
- (void)setContentSize:(CGSize)contentSize {
[super setContentSize:contentSize];
if (endUpdatesWasCalled_) {
[self notifyEndUpdatesFinished];
endUpdatesWasCalled_ = NO;
}
}
Ответ 4
Вы можете заключить свои операции в блок анимации UIView следующим образом:
- (void)tableView:(UITableView *)tableView performOperation:(void(^)())operation completion:(void(^)(BOOL finished))completion
{
[UIView animateWithDuration:0.0 animations:^{
[tableView beginUpdates];
if (operation)
operation();
[tableView endUpdates];
} completion:^(BOOL finished) {
if (completion)
completion(finished);
}];
}
Кредиты на fooobar.com/questions/57252/....
Ответ 5
Вы можете использовать tableView:willDisplayCell:forRowAtIndexPath:
как:
- (void)tableView:(UITableView *)tableView willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath {
NSLog(@"tableView willDisplay Cell");
cell.backgroundColor = [UIColor colorWithWhite:((indexPath.row % 2) ? 0.25 : 0) alpha:0.70];
}
Но это также вызывается, когда ячейка, которая уже находится в таблице, перемещается с экрана на экран, поэтому может быть не совсем то, что вы ищете. Я просто просмотрел все методы-делегаты UITableView
и UIScrollView
, и, похоже, что-то не обрабатывается сразу после добавления анимации ячейки.
Почему бы просто не вызвать метод, который вы хотите вызвать, когда анимация заканчивается после endUpdates
?
- (void)setDownloadedImage:(NSMutableDictionary *)d {
NSIndexPath *indexPath = (NSIndexPath *)[d objectForKey:@"IndexPath"];
[indexPathDelayed addObject:indexPath];
if (!([table isDragging] || [table isDecelerating])) {
[table beginUpdates];
[table insertRowsAtIndexPaths:indexPathDelayed withRowAnimation:UITableViewRowAnimationFade];
[table endUpdates];
// --> Call Method Here <--
loadingView.hidden = YES;
[indexPathDelayed removeAllObjects];
}
}
Ответ 6
Пока не найдено хорошего решения (за исключением подкласса UITableView). Я решил использовать performSelector:withObject:afterDelay:
пока. Не идеально, но выполняет свою работу.
UPDATE. Похоже, я могу использовать scrollViewDidEndScrollingAnimation:
для этой цели (это касается моей реализации, см. комментарий).