[RxSwft] RxDataSource

김범수·2022년 6월 2일
0

RxSwift

목록 보기
2/2

RxDataSource

RxSwift를 사용하여 Data를 Binding할 시 Data가 변화할 때 마다 Reload하지 않아도 된다는 미친 장점 존재

But, Table, Collection View에서 Header, Footer, Section의 개념을 사용할 수 없어서 이전까지는 Delegate Pattern을 이용하여 구현했었다.

하지만 Example 정보를 나타내는 UI에서 아래 이미지처럼 스크롤 되려면 Header 사용이 필수적이고,

이번 프로젝트에서는 능력 내에서 최대한 깔끔하게 코드를 짜고 싶어 RxDataSource를 사용하기로 결정.

⇒ RxDataSource

public struct SectionModel<Section, ItemType> {
    public var model: Section
    public var items: [Item]

    public init(model: Section, items: [Item]) {
        self.model = model
        self.items = items
    }
}
typealias ExampleSectionModel = SectionModel<SectionExampleModel, ItemExampleModel>
typealias ExampleDataSource = RxCollectionViewSectionedReloadDataSource<ExampleSectionModel>

RxDataSource에 Table, Collection View에 Binding할 모델을 SectionModel로 정의되어있다.

현재 Header에 SectionExampleModel, Item에 ItemExampleModel이 필요하므로 해당 사항에 맞춰 ExampleSectionModel 정의

exampleCollectionView.rx.setDelegate(self).disposed(by: bag)

let dataSource = RxCollectionViewSectionedReloadDataSource<ExampleSectionModel>(configureCell: { (ds, collectionView, indexPath, data) in
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: ExampleCollectionViewCell.identyfier,
                                                   for: indexPath) as? ExampleCollectionViewCell else { return UICollectionViewCell() }
    cell.setData(data)
    return cell
})
dataSource.configureSupplementaryView = {(ds, collectionView, kind, indexPath) -> UICollectionReusableView in
        guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: kind,
                                                                     withReuseIdentifier: ExampleCollectionHeaderView.identyfier, for: indexPath) as? ExampleCollectionHeaderView else {
            return UICollectionReusableView()
        }
    let section = ds.sectionModels[indexPath.row].model
    header.setData(section)
    return header
}

Driver.combineLatest(viewModel.section, viewModel.items)
    .map { [ExampleSectionModel(model: $0, items: $1)] }
    .drive(exampleCollectionView.rx.items(dataSource: dataSource))
    .disposed(by: bag)

차례로 ItemExampleModel을 Cell에 Binding - SectiontationsectionModel을 Header에 Binding - SectionExaple, ItemExample Model이 들어올때마다 CollectionViewDataSource에 Driving하는 형태.

⚠️ RxDataSource에서는 Compoment의 Configuration이 완료된 이후에 Binding, Driving 등의 작업이 가능하므로 주의!

➕ 다음에는 Cell, Header 같은 components를 XIB(NIB) 형태로 구현해보자.

매번 귀찮아서 Delegate 패턴으로 하다가 드디어 RxDataSource 해결,,

profile
iOS Developer

0개의 댓글