UICollectionView를 이용하여 그리드를 구현할 때,
점점 복잡한 구현이 생기면서, UICollectionViewDataSource
와 UICollectionViewFlowLayout
을 사용할 시 이슈가 생길때가 있다..!
🚨 Data 이슈
Controller와 UI 가 들고 있는 데이터가 일치하지 않으면,
앱에서는 어느것이 더 맞는 데이터인지 판단하기 어렵다 😖이를 근본적으로 해결하는 방식은 참인 데이터를 한개만 (Single Source of Truth) 두도록 하는 것이다!
그렇게 제안된 방법이Diffable Datasource
이다.한가지 참인 데이터를 관리하는 객체인
Snapshot
에서는
IndexPath 대신, 섹션 및 아이템에 대해서 Unique ID 를 사용한다.
🚨 Layout 이슈
기존의
UICollectionViewFlowLayout
대부분의 단순 디자인에서는 좋은 역할을 하지만..
점점 복잡한 디자인이 되었을때는, CustomLayout을 그때마다 구현해주어야했다.
이를 해결하기 위한 방법이 바로Compositional Layout
이다!Compositional Layout은 Item > Group > Section > Layout 의 구조를 갖고 있다.
var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
typealias Item = AppleFramework // AppleFramework 대신 Item 사용
enum Section {
case main
}
🎈 viewDidLoad() 메소드
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FrameworkCell", for: indexPath) as? FrameworkCell else {
return nil
}
cell.configure(item)
return cell
})
Hashable: 각각의 개체가 탐색이 빠르도록 만드는 프로토콜
: 어떤 Section에 어떤 Item을 넣을지 정한다.
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(list, toSection: .main)
dataSource.apply(snapshot)
코드가 길어질 것을 대비하여 별도의 메소드로 작성하였다 🙂
collectionView.collectionViewLayout = layout()
🎈 layout() 메소드
private func layout() -> UICollectionViewCompositionalLayout {
// fractionalWidth: group 가로의 1/3
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.33), heightDimension: .fractionalHeight(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
// group: item 한줄
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(0.33))
// 한줄에 item 3개 (가로로)
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 3)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 16, bottom: 0, trailing: 16)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
자료 출처