Как определить, что анимация закончилась на UITableView beginUpdates / endUpdates? - PullRequest
114 голосов
/ 02 октября 2011

Я вставляю / удаляю ячейку таблицы, используя insertRowsAtIndexPaths/deleteRowsAtIndexPaths, завернутый в beginUpdates/endUpdates. Я также использую beginUpdates/endUpdates при настройке rowHeight. Все эти операции по умолчанию анимированы.

Как определить, что анимация закончилась при использовании beginUpdates/endUpdates?

Ответы [ 7 ]

288 голосов
/ 20 сентября 2012

Как насчет этого?

[CATransaction begin];

[CATransaction setCompletionBlock:^{
    // animation has finished
}];

[tableView beginUpdates];
// do some work
[tableView endUpdates];

[CATransaction commit];

Это работает, потому что анимации tableView используют CALayer анимации внутри.То есть они добавляют анимацию к любому открытому CATransaction.Если open CATransaction не существует (нормальный случай), то он запускается неявно, что заканчивается в конце текущего цикла выполнения.Но если вы начнете сами, как здесь сделано, то он будет использовать это.

27 голосов
/ 12 августа 2016

Swift Version


CATransaction.begin()

CATransaction.setCompletionBlock({
    do.something()
})

tableView.beginUpdates()
tableView.endUpdates()

CATransaction.commit()
5 голосов
/ 13 января 2013

Вы можете заключить свои операции в блок анимации 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);
    }];
}

Кредиты https://stackoverflow.com/a/12905114/634940.

4 голосов
/ 02 декабря 2011

Возможным решением может быть наследование от 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;
    }
}
1 голос
/ 18 февраля 2019

Если вы ориентируетесь на iOS 11 и выше, вы должны использовать UITableView.performBatchUpdates(_:completion:) вместо:

tableView.performBatchUpdates({
    // delete some cells
    // insert some cells
}, completion: { finished in
    // animation complete
})
1 голос
/ 02 октября 2011

Не нашли хорошего решения (если не считать подкласс UITableView). Я решил использовать performSelector:withObject:afterDelay: сейчас. Не идеально, но выполняет свою работу.

ОБНОВЛЕНИЕ : Похоже, я могу использовать scrollViewDidEndScrollingAnimation: для этой цели (это относится к моей реализации, см. Комментарий).

0 голосов
/ 02 октября 2011

Вы можете использовать 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];
    }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...