📝

UICollectionViewDiffableDataSourceを使うときのテンプレート

2022/12/05に公開

毎回書くの大変なので備忘録

ベーシック

import UIKit

enum Section: Int {
  case items
}

struct Item: Hashable {
  let id: UUID = UUID()
}

class ViewController: UICollectionViewController {
  let layout = UICollectionViewCompositionalLayout.list(using: .init(appearance: .plain))
  
  let cellRegistration = UICollectionView.CellRegistration(
    handler: { (cell: UICollectionViewListCell, indexPath, item: Item) in
      var contentConfiguration = cell.defaultContentConfiguration()
      contentConfiguration.text = "Hello, World!"
      cell.contentConfiguration = contentConfiguration
    }
  )
  
  lazy var dataSource = UICollectionViewDiffableDataSource<Section, Item>(
    collectionView: collectionView,
    cellProvider: { [unowned self] (collectionView, indexPath, item) in
      collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
    }
  )
  
  var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionView.setCollectionViewLayout(layout, animated: false)
    collectionView.dataSource = dataSource
    
    snapshot.appendSections([.items])
    snapshot.appendItems([Item(), Item(), Item()], toSection: .items)
    
    dataSource.apply(snapshot)
  }
}

カスタムセル

import UIKit

enum Section: Int {
  case items
}

struct Item: Hashable {
  let id: UUID = UUID()
}

extension UICollectionViewListCell {
  func customContentConfiguration() -> CustomContentConfiguration {
    CustomContentConfiguration()
  }
}

struct CustomContentConfiguration: UIContentConfiguration, Hashable {
  var text: String = ""
  
  func updated(for state: UIConfigurationState) -> CustomContentConfiguration {
    self
  }
  
  func makeContentView() -> UIView & UIContentView {
    CustomContentView(configuration: self)
  }
}

class CustomContentView: UIView, UIContentView {
  let label: UILabel = UILabel()
  var configuration: UIContentConfiguration
  
  init(configuration: CustomContentConfiguration) {
    self.configuration = configuration
    super.init(frame: .null)
    
    label.translatesAutoresizingMaskIntoConstraints = false
    addSubview(label)
    NSLayoutConstraint.activate([
      label.topAnchor.constraint(equalTo: topAnchor),
      bottomAnchor.constraint(equalTo: label.bottomAnchor),
      label.leftAnchor.constraint(equalTo: leftAnchor),
      rightAnchor.constraint(equalTo: label.rightAnchor)
    ])
    
    label.text = configuration.text
  }
  
  @available(*, unavailable)
  required init?(coder: NSCoder) {
    fatalError("init(coder:) has not been implemented")
  }
}

class ViewController: UICollectionViewController {
  let layout = UICollectionViewCompositionalLayout.list(using: .init(appearance: .plain))
  
  let cellRegistration = UICollectionView.CellRegistration(
    handler: { (cell: UICollectionViewListCell, indexPath, item: Item) in
      var contentConfiguration = cell.customContentConfiguration()
      contentConfiguration.text = "Hello, World!"
      cell.contentConfiguration = contentConfiguration
    }
  )
  
  lazy var dataSource = UICollectionViewDiffableDataSource<Section, Item>(
    collectionView: collectionView,
    cellProvider: { [unowned self] (collectionView, indexPath, item) in
      collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: item)
    }
  )
  
  var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
  
  override func viewDidLoad() {
    super.viewDidLoad()
    
    collectionView.setCollectionViewLayout(layout, animated: false)
    collectionView.dataSource = dataSource
    
    snapshot.appendSections([.items])
    snapshot.appendItems([Item(), Item(), Item()], toSection: .items)
    
    dataSource.apply(snapshot)
  }
}

Discussion