DiffableDataSource で apply 後の UICollectionView の contentSize を取得する
問題
UICollectionViewDataSource を使っている場合では、 下記のように reloadData 直後には collectionView の contentSize が更新されている。
collectionView.reloadData()
collectionView.layoutIfNeeded()
// collectionView.contentSize が更新されている
しかし DiffalbleDataSource を使っている場合には、 apply 直後では、collectionView の contentSize は更新されていない(レイアウトの組み方によってはその限りじゃないかも)。
dataSource.apply(snapshot)
collectionView.layoutIfNeeded()
// collectionView.contentSize は更新前の値のまま
reloadData はサイズ計算が同期的に行われているけど、 apply の場合はサイズ計算が非同期で行われているぽい。
対応
DiffalbleDataSource の apply メソッドは下記のようなインターフェースになっており、 アニメーションの有無と、 apply 後に実行するクロージャを渡すことができる。
func apply(_ snapshot: NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType>, animatingDifferences: Bool = true, completion: (() -> Void)? = nil)
そのため、 apply 後の contentSize を取得したければ completion 内で取得すると良さそう。
アニメーションが不要な場合には animatingDifferences を false にするのでも大丈夫だった。
ちなみに apply の場合には layoutIfNeeded は不要だった。
dataSource.apply(snapshot, animatingDifferences: true) { [weak self] in // collectionView.contentSize は更新後の値 } dataSource.apply(snapshot, animatingDifferences: false) // collectionView.contentSize は更新後の値