Diffable DataSource & Compositional Layout

슆공부·2022년 7월 1일
0

기존 FlowLayout

  • 기존 구현은 간단하고 유연
  • 보통 Controller 가 데이터 받아와서, UI 에게 변경을 알림
  • 점점 복잡한 구현이 생기면서, 기존방식 사용시 이슈가 생길때가 있음
  • Controller, UI 가 들고 있는 데이터 사이에서 일치 하지 않음
    • 앱에서는 어느것이 더 맞는 데이터인지 판단하기 어려움
  • 근본적인 문제 해결의 고민 증가

Single Source Of Truth Data 의 필요성 증가

  • 기존의 구현 방식에서 어떤 데이터(Controller, UI가 각각 데이터를 들고 있음)가 참인지 알기 어려웠음
  • 따라서, 근본적인 문제 해결 방식은 참인 데이터를 한개만 두도록 함 → Single Source of Truth
  • 그렇게 제안된 방법이 Diffable Datasource

Snapshot 의 도입

  • 한가지 참인 데이터를 관리하는 객체
  • Indexpath 를 쓰지 않고,
  • 섹션 및 아이템에 대해서 Unique ID 를 사용함
    - Unique + Hashable

Compositional Layout 의 등장

중요 개념

  • 기존 UICollectionView 에서 Data, Presentation 구현 방법은 에러가 생길수 있음
    • AS-IS : UICollectionViewDataSource
    • TO-BE : UICollectionViewDiffableDataSource
  • 기존 UICollectionView 에서 layout 구현관련해서 복잡한 구현시, 난이도가 갑자기 올라감
    • AS-IS : UICollectionViewFlowLayout
    • TO-BE : UICollectionViewCompositionalLayout

Collection view 구성

collection view는 여러 개의 items를 반복해서 보여줍니다. 또한 이 item group을 Sections으로 보여줍니다.
여기서 한 section의 item들은 보통 서로 연관이 되어 있습니다.
UICollectionViewCompositionalLayout
iOS13 전에는, UICollectionViewFlowLayout을 사용해서 레이아웃을 구성했습니다.
하지만 이것은 레이아웃을 구성하는데 한계가 있고, 세 개의 columns 나 다른 종류의 collection view를 구성하는 등의 복잡한 레이아웃은 구현하는 것이 불가능했습니다.
그래서 나온 것이 compositional layout입니다.
여기서 애플은 Groups의 개념을 도입했습니다. 적은 양의 코드로 좀 더 정교한 레이아웃을 구성할 수 있습니다.

diffable datasouce 사용

 enum Section {
   case main
 }
 typealias Item = BannerInfo
 
 var datasource: UICollectionViewDiffableDataSource<Section, Item>!```

뷰 초기화할 시
```swift
 //presentation
   datasource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
     guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "BannerCell", for: indexPath) as? BannerCell else {
       return nil
     }
     cell.configure(item)
     cell.backgroundColor = self.colors[indexPath.row]
     return cell
   })
   
   //data
   var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
   snapshot.appendSections([Section.main])
   snapshot.appendItems(bannerInfo, toSection: .main)
   datasource.apply(snapshot)
   
   //layout
   collectionView.collectionViewLayout = layout()

layout 메서드 구현

 private func layout() -> UICollectionViewCompositionalLayout {
    let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalHeight(1))
    let item = NSCollectionLayoutItem(layoutSize: itemSize)
    let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.8), heightDimension: .absolute(200))
    let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
    let section = NSCollectionLayoutSection(group: group)
    section.orthogonalScrollingBehavior = .groupPagingCentered
    section.interGroupSpacing = 20
    let layout = UICollectionViewCompositionalLayout(section: section)
    return layout
  }

여기서 fractional width와 height을 1로 설정하였는데, 이것은 이 아이템을 포함하는 Group에서의 넓이와 높이이다.

hashable

var dataSource: UICollectionViewDiffableDataSource<Section, AppleFramework>! 타입인데ㅇ
강제 옵셔널 바인딩해서 이건 꼭 있을 거야라고 지정해놓음 -> iboutlet 이런것처럼? 찾아보기
typealias
uicollectionviewcel 을 as 캐스팅해주어야 메서드 쓸수있는이유
else 일때 왜 nil을

private 지정하면 쓸수있는 범위가 뷰컨만?

0개의 댓글