🍎

[Swift]UICollectionViewの進化:Diffable Data Source編

2022/03/12に公開

前回

CollectionViewの構築方法の変更点として、
前回記事ではLayoutに関して記載しました。
この記事ではData Sourceに関する変更点をまとめています。
Layoutに関しての前回記事はこちら
記事内で参考資料としているWWDCのスライド資料です。
https://devstreaming-cdn.apple.com/videos/wwdc/2019/220xl4hxzzr7b19/220/220_advances_in_ui_data_sources.pdf?dl=1

Data Source

これまで使用されているUICollectionViewDataSourceは、
以下のテンプレのようにシンプルかつ柔軟性のある使い方が出来ます。

UICollectionViewDataSource
// MARK: UICollectionViewDataSource
func numberOfSections(in collectionView: UICollectionView) -> Int {
 return models.count
}
func collectionView(_ collectionView: UICollectionView,
 numberOfItemsInSection section: Int) -> Int {
 return models[section].count
}
func collectionView(_ collectionView: UICollectionView,
 cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
 let cell = collectionView.dequeueReusableCell(withReuseIdentifier: reuseIdentifier,
 for:indexPath)
 // configure cell
 return cell
}

ただこちらも1点大きな問題を抱えていました。
アプリが複雑な作りになっていくほど、
UIの更新を生成するのは困難な場合があるという問題です。
具体的な内容が公式で挙げられてますので見てみましょう。
numberOfItemsInSectionでUI側からdata Sourceに必要なセルの数を要求します。

②APIのレスポンス等からUIの更新を行おうとします。

③クラッシュ

このクラッシュ原因の内容としては、
performBatchUpdatesを実行する前と後で、
UICollectionViewの更新でsectionの数が変わります。
その際controllerとUI側でsectionの数をイコールにしておく必要があるのです。
この解決策として登場したのが、Diffable Data Sourceです。

Diffable Data Source

UICollectionViewDataSourceの課題として前途しました、
UIの更新時に使用されるperformBatchUpdatesから、
applyというメソッドを使うことに変更することで、課題の解消を試みます。

Diffable Data Sourceで重要となる概念として、Snapshotsというものがあります。
こちらをまず解説していきます。

Snapshots

UI状態の真偽を持ち、
IndexPathsは不要で、セクションとアイテムで一意の識別子(Identifier)を使用します。
applyメソッドを使いUI更新を適用させます。
どのような流れなのか以下の図を見ながら解説します。

  1. Snapshotの構築(Current Snapshot
  2. UI更新したい内容の新しいSnapshotを作成(New Snapshot
  3. applyメソッドでUIに適用する

Snapshotsの構築方法は例として以下の図のようになります。

Diffable Data Sourceの感想

performBatchUpdatesでのクラッシュへの解消、
またSnapshotsというUI状態の持つクラスの登場で、
最初のうちは慣れが必要ですが、
よりシンプルながら複雑なUIの更新が安全に出来るようになったと思います。

Discussion