[iOS | Swift] UICollectionView: Diffable Datasource 와Compositional Layout 를 이용한 구현 유연화

someng·2022년 9월 21일
0

iOS

목록 보기
5/33

UICollectionView를 이용하여 그리드를 구현할 때,
점점 복잡한 구현이 생기면서, UICollectionViewDataSourceUICollectionViewFlowLayout을 사용할 시 이슈가 생길때가 있다..!

🚨 Data 이슈

Controller와 UI 가 들고 있는 데이터가 일치하지 않으면,
앱에서는 어느것이 더 맞는 데이터인지 판단하기 어렵다 😖

이를 근본적으로 해결하는 방식은 참인 데이터를 한개만 (Single Source of Truth) 두도록 하는 것이다!
그렇게 제안된 방법이 Diffable Datasource 이다.

한가지 참인 데이터를 관리하는 객체인 Snapshot에서는
IndexPath 대신, 섹션 및 아이템에 대해서 Unique ID 를 사용한다.

🚨 Layout 이슈

기존의 UICollectionViewFlowLayout 대부분의 단순 디자인에서는 좋은 역할을 하지만..
점점 복잡한 디자인이 되었을때는, CustomLayout을 그때마다 구현해주어야했다.
이를 해결하기 위한 방법이 바로 Compositional Layout이다!

Compositional Layout은 Item > Group > Section > Layout 의 구조를 갖고 있다.

🧜🏻‍♀️ 프로젝트 예시 (애플 프레임워크)

1. Diffable Datasource 만들기

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
})

2. AppleFramework의 dataType을 Hashable 로 변형

Hashable: 각각의 개체가 탐색이 빠르도록 만드는 프로토콜

3. Snapshot을 이용해 Data 다루기

: 어떤 Section에 어떤 Item을 넣을지 정한다.

var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(list, toSection: .main)
dataSource.apply(snapshot)

4. Compositional Layout

코드가 길어질 것을 대비하여 별도의 메소드로 작성하였다 🙂

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
}

🥳 프로젝트 결과화면

자료 출처

패스트캠퍼스) 왕초보를 위한, 한 번에 끝내는 iOS 앱 개발 바이블

profile
👩🏻‍💻 iOS Developer

0개의 댓글