본문으로 바로가기

[iOS] 리스트 및 그리드 뷰 구성하기

category iOS 2022. 7. 22. 11:43
728x90

1. Layout: CompositionalLayout

Layout을 구성하는 요소를 관리

Item < Group < Section < Layout

// 예시
private func layout() -> UICollectionViewCompositionalLayout {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
        
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(200))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
        
    let section = NSCollectionLayoutSection(group: group)
    
    let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50))
    let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
    section.boundarySupplementaryItems = [header]
        
    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
}

collectionView.collectionViewLayout = layout()

 

2. Presentation: DiffableDataSource

Single Source Of Truth Data의 필요성 증가로 인해 DiffableDataSource를 사용을 권장한다.

UICollectionViewDiffableDataSource<Section, Item> 클래스를 사용하고,

Section과 Item 타입에 대해 정의해야한다.

// 예시
var dataSource: UICollectionViewDiffableDataSource<Section, Item>!

enum Section: CaseIterable {
    case main
    case sub
    var title: String {
        switch self {
            case .main: return "Main"
            case .sub: return "Sub"
        }
    }
}

typealias Item = Person
struct Person: Hashable {
    let name: String
}
dataSource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: /*collectionView*/,
	cellProvider: { collectionView, indexPath, item in
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: /*"UserCell"*/,
        for: indexPath) as? /*UserCell*/ as {
        return nil
    }
    cell.configure(item)
    return cell
})
// 헤더뷰 추가
datasource.supplementaryViewProvider = { (collectionView, kind, indexPath) in
    guard let header = collectionView.dequeueReusableSupplementaryView
        (ofKind: UICollectionView.elementKindSectionHeader,
        withReuseIdentifier: /*"HeaderView"*/, for: indexPath) as? /*HeaderView*/ else {
        return nil
    }
    
    //let section = Section.allCases[indexPath.section]
    return header
}

3. Data: Snapshot

한가지 참인 데이터를 관리하는 객체

Unique ID를 사용하여 HashTable을 구성한다.

// 예시
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections(Section.allCases)
snapshot.appendItems(/*listMain*/, toSection: .main)
snapshot.appendItems(/*listSub*/, toSection: .sub)
dataSource.apply(snapshot)

 

+. PageController

CompositionalLayout에 아래 옵션 중 하나를 추가한다.

// 1. 연속적인 스크롤
section.orthogonalScrollingBehavior = .continuous 
// 2. 좌측 기준 스크롤
section.orthogonalScrollingBehavior = .groupPaging
// 3. 중앙 기준 스크롤
section.orthogonalScrollingBehavior = .groupPagingCentered

아래 방법으로 인덱스를 알 수 있다.

section.visibleItemsInvalidationHandler = { (item, offset, env) in
    let index = Int(offset.x / env.container.contentSize.width)	
}

 

UIScrollViewDelegate의 아래 함수를 구현해서 움직임을 제어할 수 있다.

  • scrollViewDidScroll
  • scrollViewDidEndDecelerating

 

728x90