1. Qiita
  2. 投稿
  3. iOS

UITableView / UICollectionView の reloadData が完了した直後にセルを参照したい

  • 22
    いいね
  • 3
    コメント
この記事は最終更新日から1年以上が経過しています。

 UITableView や UICollectionView の reloadData を実行した時点ではまだセルのレイアウトが完了していないことがあります。

-visibleCells
[tableView reloadData];
NSArray *cells = [tableView visibleCells];
-indexPathsForVisibleItems
[collectionView reloadData];
NSArray *indexPaths = [collectionView indexPathsForVisibleItems];

 このときの cells, indexPaths には reloadData で反映する前のセルやインデックス、もしくは nil が返ってくることがあります。それだと困るので、reloadData が完了した後でセルやインデックスを参照できるようにするために強制レイアウトを実行します。

-layoutSubviews
[tableView reloadData];
[tableView layoutIfNeeded];
NSArray *cells = [tableView visibleCells];

 強制レイアウトでは layoutSubviews ではなく layoutIfNeeded を使用します※。これで reloadData で反映したセルがおそらく得られるかと思いますが、手元で検証したところ、これでもうまくいかない場合があるようです。なので代わりに GCD で対応します。

dispatch_async()
[tableView reloadData];

dispatch_async(dispatch_get_main_queue(), ^{
    NSArray *cells = [tableView visibleCells];
});

UIView Class Reference – layoutSubviews

layoutSubviews
~
You should not call this method directly. If you want to force a layout update, call the setNeedsLayout method instead to do so prior to the next drawing update. If you want to update the layout of your views immediately, call the layoutIfNeeded method.