insertRowsAtIndexPaths/deleteRowsAtIndexPaths
wrapped in を使用してテーブルセルを挿入/削除していますbeginUpdates/endUpdates
。beginUpdates/endUpdates
rowHeightを調整するときにも使用しています。これらの操作はすべて、デフォルトでアニメーション化されています。
使用中にアニメーションが終了したことをどのように検出できbeginUpdates/endUpdates
ますか?
insertRowsAtIndexPaths/deleteRowsAtIndexPaths
wrapped in を使用してテーブルセルを挿入/削除していますbeginUpdates/endUpdates
。beginUpdates/endUpdates
rowHeightを調整するときにも使用しています。これらの操作はすべて、デフォルトでアニメーション化されています。
使用中にアニメーションが終了したことをどのように検出できbeginUpdates/endUpdates
ますか?
回答:
これはどうですか?
[CATransaction begin];
[CATransaction setCompletionBlock:^{
// animation has finished
}];
[tableView beginUpdates];
// do some work
[tableView endUpdates];
[CATransaction commit];
これは、tableView CALayer
アニメーションが内部でアニメーションを使用するため機能します。つまり、開いているにアニメーションを追加しますCATransaction
。オープンCATransaction
が存在しない場合(通常の場合)、1つが暗黙的に開始され、現在の実行ループの終わりに終了します。しかし、ここで行うように、自分で始めた場合は、それを使用します。
completionBlock
前beginUpdates
とendUpdates
スニペットのように?
[CATransaction commit]
前ではなく後に呼び出す必要があります[tableView endUpdates]
。
考えられる解決策は、UITableViewがコンテンツサイズを調整して追加または削除された行に一致するため、呼び出し元のUITableViewから継承してそれをendUpdates
上書きすることですsetContentSizeMethod
。このアプローチはでも機能するはずです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;
}
}
次のように、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);
}];
}
endUpdates
、アニメーションが完了する前に呼び出されました。
まだ良い解決策を見つけていません(UITableViewのサブクラス化を除く)。とりあえず使うことにしましたperformSelector:withObject:afterDelay:
。理想的ではありませんが、仕事を成し遂げます。
更新:私はscrollViewDidEndScrollingAnimation:
この目的に使用できるように見えます(これは私の実装に固有です、コメントを参照してください)。
scrollViewDidEndScrollingAnimation
setContentOffset
and scrollRectToVisible
次の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
delegateメソッドを調べたところ、アニメーションが挿入された直後に何も処理するようには見えません。
の後にアニメーションが終了したときに呼び出されるメソッドを呼び出すだけでは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];
}
}
willDisplayCell
は思わないでください。すべてが落ち着いた後にのみ視覚的な更新を行う必要があるので、アニメーションの後でそれを行う必要があります。
-scrollToRowAtIndexPath:atScrollPosition:animated:
れます。