How to detect that animation has ended on UITableView beginUpdates/endUpdates?

柔情痞子 提交于 2019-11-26 08:44:44

问题


I am inserting/deleting table cell using insertRowsAtIndexPaths/deleteRowsAtIndexPaths wrapped in beginUpdates/endUpdates. I am also using beginUpdates/endUpdates when adjusting rowHeight. All these operations are animated by default.

How can I detect that animation has ended when using beginUpdates/endUpdates?


回答1:


What about this?

[CATransaction begin];

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

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

[CATransaction commit];

This works because the tableView animations use CALayer animations internally. That is, they add the animations to any open CATransaction. If no open CATransaction exists (the normal case), then one is implicitly began, which is ended at the end of the current runloop. But if you begin one yourself, like is done here, then it will use that one.




回答2:


Swift Version


CATransaction.begin()

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

tableView.beginUpdates()
tableView.endUpdates()

CATransaction.commit()



回答3:


You can enclose your operation(s) in UIView animation block like so:

- (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);
    }];
}

Credits to https://stackoverflow.com/a/12905114/634940.




回答4:


A possible solution could be to inherit from the UITableView on which you call endUpdates and overwrite its setContentSizeMethod, since UITableView adjusts its content size to match the added or removed rows. This approach should also work for reloadData.

To ensure that a notification is sent only after endUpdates is called, one could also overwrite endUpdates and set a flag there.

// 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;
    }
}



回答5:


If you're targeting iOS 11 and above, you should use UITableView.performBatchUpdates(_:completion:) instead:

tableView.performBatchUpdates({
    // delete some cells
    // insert some cells
}, completion: { finished in
    // animation complete
})



回答6:


Haven't found a good solution yet (short of subclassing UITableView). I've decided to use performSelector:withObject:afterDelay: for now. Not ideal, but gets the job done.

UPDATE: It looks like I can use scrollViewDidEndScrollingAnimation: for this purpose (this is specific to my implementation, see comment).




回答7:


You can use tableView:willDisplayCell:forRowAtIndexPath: like:

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

But this will also get called when a cell that is already in the table moves from off the screen to on the screen so it may not be exactly what you are looking for. I just looked through all the UITableView and UIScrollView delegate methods and there doesnt appear to be anything to handle just after a cell is inserted animation.


Why not just call the method you want to be called when the animation ends after the 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];
    }
}


来源:https://stackoverflow.com/questions/7623771/how-to-detect-that-animation-has-ended-on-uitableview-beginupdates-endupdates

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!