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)

Apple Developer Documentation

そのため、 apply 後の contentSize を取得したければ completion 内で取得すると良さそう。
アニメーションが不要な場合には animatingDifferences を false にするのでも大丈夫だった。

ちなみに apply の場合には layoutIfNeeded は不要だった。

dataSource.apply(snapshot, animatingDifferences: true) { [weak self] in
    // collectionView.contentSize は更新後の値
}

dataSource.apply(snapshot, animatingDifferences: false)
//  collectionView.contentSize は更新後の値