我使用insertRowsAtIndexPaths/deleteRowsAtIndexPaths
中包含的beginUpdates/endUpdates
插入/删除表格单元格。我在调整rowHeight时也使用beginUpdates/endUpdates
。默认情况下,所有这些操作都是动画的。
使用beginUpdates/endUpdates
时如何检测动画已结束?
答案 0 :(得分:286)
这个怎么样?
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// animation has finished
}];
[tableView beginUpdates];
// do some work
[tableView endUpdates];
[CATransaction commit];
这是有效的,因为tableView动画在内部使用CALayer
动画。也就是说,他们将动画添加到任何打开的CATransaction
。如果不存在open CATransaction
(正常情况),则会隐式启动一个,这将在当前runloop结束时结束。但如果你自己开始,就像在这里完成一样,那么它将使用那个。
答案 1 :(得分:27)
Swift版
CATransaction.begin()
CATransaction.setCompletionBlock({
do.something()
})
tableView.beginUpdates()
tableView.endUpdates()
CATransaction.commit()
答案 2 :(得分:5)
您可以将操作包含在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);
}];
}
答案 3 :(得分:4)
可能的解决方案是从您调用endUpdates
的UITableView继承并覆盖其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 :(得分:1)
还没有找到一个好的解决方案(没有子类化UITableView)。我现在决定使用performSelector:withObject:afterDelay:
。不理想,但完成工作。
更新:看起来我可以将scrollViewDidEndScrollingAnimation:
用于此目的(这是针对我的实现,请参阅评论)。
答案 5 :(得分:1)
如果您定位到iOS 11及更高版本,则应改用UITableView.performBatchUpdates(_:completion:)
:
tableView.performBatchUpdates({
// delete some cells
// insert some cells
}, completion: { finished in
// animation complete
})
答案 6 :(得分:0)
您可以使用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];
}
}