iOS・Android

【公式チュートリアル解説】UICollectionViewのUICollectionLayoutListConfigurationでListレイアウトを作成する。

iOS・Android
この記事は約9分で読めます。

UIKitのチュートリアルを参考にCompositionalLayoutでListレイアウトを作成する手順と考え方を整理しました。

公式のチュートリアルと突き合わせると、理解が捗る資料を目指して作成しました。

対象読者:

  • 公式のチュートリアルを実践済み
  • 全体的な構成を俯瞰して把握することに苦労している人。

チュートリアルの概要:

公式が提供している「UIKit essentials Creating a list view」を題材とします。

Creating a list view | Apple Developer Documentation
In this tutorial, you’ll create your app’s root view, a collection view with a list layout that displays the user’s daily reminders.

このチュートリアルでは、データの更新が行えるリストレイアウトを作成します。

対象のレイアウト

登場人物:

CompositionalLayoutでListを構築する上で、必要な登場人物を整理しましょう。

レイアウト構成とデータを持つ場所が違うため、それぞれについて以下で解説します。

リストレイアウトを構成

  • UICollectionViewController:コレクションビューと関連する機能を統合的に管理
  • UICollectionViewCompositionalLayout:
    • UICollectionLayoutListConfiguration:リストの1つのセルの外観と、コレクションビュー全体のレイアウト情報を保持
  • CellRegistration:デフォルトのセルの外観とデータを管理。
    • defaultContentConfiguration:デフォルトのセルの外観情報を保持。

リストのセルに表示するコンテンツデータ

  • ReminderModel

リストのセルに表示するコンテンツデータの管理

  • Snapshot(NSDiffableDataSourceSnapshot):リストに表示するデータとデータモデルの整合性を保つためのある時点のデータを提供。
  • DataSource:コレクションビューのデータの更新に基づき、ユーザーインターフェイスの更新を担当。
    • dequeueConfiguredReusableCell:CellRegistrationと照らし合わせ、必要に応じて新しいコンテンツデータを代入し、Viewを描画。

登場人物たちの振る舞いを概観する

このコードは、MVCと呼ばれる、公式が推奨とされている構成で書かれています。

ViewとModelは完全に分離されており、Controllerに仲介されます。

チュートリアルにて登場した登場人物たちを、MVCモデルに当てはめてみました。

手順:

  1. リストレイアウトを構成するリストの1つのセルの外観とコレクションビュー全体のレイアウトを決める。
  2. コレクションビュー全体のの構成要素としてリストレイアウトを設定する。
    (デフォルトのセルレイアウトを確定させる)
  3. デフォルトのセルのレイアウトに、表示するコンテンツ(タイトルなど)のデフォルトのデータを与える。
  4. セルをデータソースに接続。データソースの更新に応じてレイアウトを変更する。

リストレイアウトを構成するリストの1つのセルの外観とコレクションビュー全体のレイアウトを決める

登場人物

  • UICollectionViewCompositionalLayout:
    • UICollectionLayoutListConfiguration:リストの1つのセルの外観と、コレクションビュー全体のレイアウト情報を保持

以下コードが該当部分です。

private func listLayout() -> UICollectionViewCompositionalLayout {
        var listConfiguration = UICollectionLayoutListConfiguration(appearance: .grouped)
        listConfiguration.showsSeparators = false
        listConfiguration.backgroundColor = .clear
        return UICollectionViewCompositionalLayout.list(using: listConfiguration)
    }

ここではUICollectionViewCompositionalLayoutを継承したUICollectionLayoutListConfigurationを用い、リストの1つのセルの外観と、コレクションビュー全体のレイアウトを設定しています。

コレクションビューの構成要素としてリストレイアウトを設定する

登場人物

  • UICollectionViewController:コレクションビューと関連する機能を統合的に管理

UICollectionViewController内のセクションの位置や外観の情報として、先ほど作成したlistLayoutを渡します。これにより、セルのデフォルトの外観の構成情報(defaultContentConfiguration)と コレクションビュー全体のセルの配置や全体的なレイアウトが確定します。

collectionView.collectionViewLayout = listLayout

デフォルトのセルのレイアウトに、表示するコンテンツ(タイトルなど)のデフォルトのデータを与える。

登場人物

  • CellRegistration:デフォルトのセルの外観とデータを管理。
    • defaultContentConfiguration:デフォルトのセルの外観情報を保持。
  • ReminderModel

CellRegistrationにデータを渡し、表示するセルのデフォルトの外観とデータの初期の状態を定義します。

let cellRegistration = UICollectionView.CellRegistration {
            (cell: UICollectionViewListCell, indexPath: IndexPath, itemIdentifier: String) in
            let reminder = Reminder.sampleData[indexPath.item]
            var contentConfiguration = cell.defaultContentConfiguration()
            contentConfiguration.text = reminder.title
            cell.contentConfiguration = contentConfiguration
        }

セルをデータソースに接続。データソースの更新に応じてレイアウトを変更する。

登場人物

  • Snapshot(NSDiffableDataSourceSnapshot):リストに表示するデータとデータモデルの整合性を保つためのある時点のデータを提供。
  • DataSource:コレクションビューのデータの更新に基づき、ユーザーインターフェイスの更新を担当。
    • dequeueConfiguredReusableCell:CellRegistrationと照らし合わせ、必要に応じて新しいコンテンツデータを代入し、Viewを描画。

Snapshot(NSDiffableDataSourceSnapshot) を作成します。

        var snapshot = Snapshot()
        snapshot.appendSections([0])
        snapshot.appendItems(Reminder.sampleData.map { $0.title })
        dataSource.apply(snapshot)

NSDiffableDataSourceSnapshot は、データソースに対して変更を適用するためのスナップショットを表現するクラスです。古いデータセットと新しいデータセットの差分を計算し、dataSourceに適用します。

dataSource.apply(snapshot) にて dataSourcesnapshotが反映されています。

レイアウトの更新を行いましょう。

        dataSource = DataSource(collectionView: collectionView) {
            (collectionView: UICollectionView, indexPath: IndexPath, itemIdentifier: String) in
            
            return collectionView.dequeueConfiguredReusableCell(
                using: cellRegistration, for: indexPath, item: itemIdentifier)
        }

dequeueConfiguredReusableCellに、先ほど作成したconfigurationを渡し、必要に応じて新しいコンテンツデータを代入し、Viewを描画を行います。

おすすめ情報

2020年のWWDCにて、「Lists in UICollectionView」と「Advances in Collection View Layout」という発表があります。合わせて参照すると理解が深まりそうです。

Lists in UICollectionView - WWDC20 - Videos - Apple Developer
Learn how to build lists and sidebars in your app with UICollectionView. Replace table view appearance while taking advantage of the full...
Advances in Collection View Layout - WWDC19 - Videos - Apple Developer
Collection View Layouts make it easy to build rich interactive collections. Learn how to make dynamic and responsive layouts that range...

参考

UICollectionView | Apple Developer Documentation
An object that manages an ordered collection of data items and presents them using customizable layouts.
NSDiffableDataSourceSnapshot | Apple Developer Documentation
A representation of the state of the data in a view at a specific point in time.
UICollectionViewCompositionalLayout | Apple Developer Documentation
A layout object that lets you combine items in highly adaptive and flexible visual arrangements.
UICollectionViewDiffableDataSource | Apple Developer Documentation
The object you use to manage data and provide cells for a collection view.
NSCollectionViewDiffableDataSourceReference | Apple Developer Documentation
The Swift representation of the Objective-C object you use to manage data and provide items for a collection view.
defaultContentConfiguration() | Apple Developer Documentation
Retrieves a default list content configuration for the cell’s style.