*컬렉션뷰 cell 등록 ⇒ 레이아웃 구현 ⇒ datasource (cellProvider) ⇒ snapshot을 만들어서 datasource에 넣어준다
// 섹션
enum MovieQuery: String, Hashable {
case now_playing = "상영중인 영화"
case upcoming = "상영예정인 영화"
}
// 각 섹션 별 아이템 (Result타입의 데이터를 전달)
enum MovieItem: Hashable {
case oneItemCell(Result)
case twoItemCell(Result)
}
typealias Section = MovieQuery
typealias Item = MovieItem
// datasource의 섹션과 그 아이템의 타입으로 쓰인다
private var dataSource: **UICollectionViewDiffableDataSource**<Section, Item>?
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: .init())
collectionView.**setCollectionViewLayout**(createCollectionViewLayout(), animated: true)
// 📌 section index별로 UICollectionLayoutSection을 만든다
func createCollectionViewLayout() -> UICollectionViewCompositionalLayout {
return UICollectionViewCompositionalLayout(**sectionProvider**: { [weak self] **index**, env in
guard let weakSelf = self else { fatalError() }
weakSelf.createSection(by: **index**)
})
}
// 📌 index를 받아서 UICollectionLayoutSection을 만든다
func createSection(by index: Int) -> NSCollectionLayoutSection {
switch index {
case 0:
return createNowSection()
case 1:
return createUpcomingSection()
default: break
}
}
// 📌 NOW 섹션 (item => group => section)
func createNowSection() -> NSCollectionLayoutSection {
// supplementaryView (ex. header)
let titleSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .absolute(50))
let titleSupplementary = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: titleSize,
elementKind: .elementKinSectionHeader, // Header
alignment: .top)
// item
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1.0), heightDimension: .fractionalHeight(1.0))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// group
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .absolute(450))
let group = NSCollectionLayoutGroup**.horizontal**(layoutSize: groupSize, subitems: [item]) // 수직 / 수평 방향 지정
// section
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .groupPaging // 스크롤 애니메이션?
section.interGroupSpaing = 20 // group간격
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 10, bottom: 35, trailing: 10) // section 패딩
section.boundarySupplemnetaryItems = [titileSupplemnetary] // 위에 헤더 supplementaryView 추기
}
// 섹션
enum MovieQuery: String, Hashable {
case now_playing = "상영중인 영화"
case upcoming = "상영예정인 영화"
}
// 각 섹션 별 아이템 (Result타입의 데이터를 전달)
enum MovieItem: Hashable {
case oneItemCell(Result)
case twoItemCell(Result)
}
typealias Section = MovieQuery
typealias Item = MovieItem
private var dataSource: UICollectionViewDiffableDataSource<Section, Item>?
// ✅ cell 생성
dataSource = **UICollectionViewDiffableDataSource**(collectionView: collectionView, **cellProvider**: {collectionView, indexPath, item in
switch item {
case let .oneItemCell(data):
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: NowPlayingCell.self,
for: indexPath) as? NowPlayingCell else {return UICollectionViewCell()}
cell.configure(data)
return cell
case let .twoItemCell(data):
...
}
})
// ✅ supplementaryView(헤더) 생성
dataSource?.supplementaryViewProvider = { [weak self] (collectionView, kind, indexPath) -> **UICollectionReusableView**? in
guard kind == UICollectionView.elementKindSectionHeader,
let weakSelf = self,
let **header** = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
withReuseIdentifier: MovieSectionHeader.identifier,
for: indexPath) as? MovieSectionHeader else { return nil }
let section = weakSelf.dataSource?.snapshot().sectionIdentifiers[indexPath.section]
switch section {
case .now_playing:
header.configure(title: "현재 상영중인 영화")
case .upcoming:
header.configure(title: "상영 예정인 영화")
default: break
}
return **header**
}
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([Section.now_playing])
snapshot.appendItems(nowMovieItem, toSEction: Section.now_playing)
snapshot.appendSections([Section.upcoming])
snapshot.appendItems(upcomingMovieItem, toSEction: Section.upcoming)
// 📌 snapshot을 datasource에 적용
dataSource?.apply(snapshot)