본문 바로가기
iOS

[iOS] RxDataSource 😡

by yangsubinn 2022. 5. 17.
😡 야심차게 Rx로 컬렉션뷰/테이블뷰를 구성했는데 .. 갑자기 .. 섹션이 필요하다..? 그럼 RxDataSource를 쓰세요..

 

RxDataSource를 사용해야 하는 이유❓

Rx를 통해 collectionView를 바인딩해서 사용하고 있었습니다 ..

섹션이 하나인 경우에는 RxSwift , RxCocoa dataSource 만으로도 충분히 사용할 수 있는데,

섹션이 여러개가 되는 경우에는 구현이 조금 어렵습니다.

이런 경우 RxDataSource를 통해 여러 섹션의 여러 아이템을 넣어 구현할 수 있습니다.

 

GitHub - RxSwiftCommunity/RxDataSources: UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates,

UITableView and UICollectionView Data Sources for RxSwift (sections, animated updates, editing ...) - GitHub - RxSwiftCommunity/RxDataSources: UITableView and UICollectionView Data Sources for RxSw...

github.com

 

사용해보겠슴니다 🔫

아래는 RxDataSource를 적용하기 전의 컬렉션뷰입니다.

한 줄에 최대 3개의 태그만 들어가야 하며, 태그별로 길이가 달랐기 때문에

섹션을 통해 한 섹션에 3개의 태그씩 들어가게 하려 합니다.

(왼쪽) 변경 전, RxDataSource 섹션 분리 X (오른쪽) 변경 후, RxDataSource 섹션 분리 O

 

 

 

1️⃣ pod install

pod 'RxDataSources', '~> 5.0'

먼저 pod을 설치해줍니다. 위에 있는 RxDataSource 깃허브에 들어가도 확인하실 수 있슴니다.

 

 

2️⃣ section model 만들기

섹션으로 나눠서 데이터를 넣어주기 위한 모델을 만들어줍니다.

struct CategorySectionModel {
	// var header: String
  var items: [Category]
  
  init(items: [Category]) {
    self.items = items
  }
	
	// header을 받는 경우
	// init(header: String, item: [Category]) {
	//   self.header = header
	//   self.items = items
	// }
}

extension CategorySectionModel: SectionModelType {
  typealias item = Category
  
  init(original: CategorySectionModel, items: [item]) {
    self = original
    self.items = items
  }
}

제가 받고자 하는 데이터 리스트가 섹션별 카테고리의 리스트이기 때문에

Category의 배열을 items로 받았습니다.

또한 섹션의 헤더 타이틀을 받는 경우, header을 선언해서 받는 등 섹션별로 넣고자 하는 데이터를 추가해주시면 됩니다.

이런 section에 넣을 데이터 모델은 위와 같이

SectionModelType을 준수해야 SectionModel로 활용할 수 있습니다.

public protocol SectionModelType {
    associatedtype Item

    var items: [Item] { get }

    init(original: Self, items: [Item])
}

 

 

3️⃣ DataSource 구현

다음에로 VC에서 사용할 dataSource를 구현해줬습니다.

private lazy var dataSource = RxCollectionViewSectionedReloadDataSource<CategorySectionModel> (configureCell: { dataSource, collectionView, indexPath, item in
    guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CategoryCVC.className, for: indexPath) as? CategoryCVC else { return UICollectionViewCell() }
    cell.categoryLabel.text = item.rawValue
    return cell
  })

RxCollectionViewSectionedReloadDataSource를 통해 dataSource 객체를 만들었고,

이 객체는 SectionModelType를 받기 때문에 앞에서 생성한 CategorySectionModel을 넣어줬습니다.

configureCell은 dataSource, collectionView, indexPath, item을 받아 cell을 리턴하는 클로져로,

여기서 아이템은 CategorySectionModel의 item을 말합니다 !

items의 item을 받아와 셀의 categoryLabel.text에 넣어줬습니다.

struct CategorySectionModel {
  var items: [Category]
  
  init(items: [Category]) {
    self.items = items
  }
}

extension CategorySectionModel: SectionModelType {
  **typealias item = Category**
  
  init(original: CategorySectionModel, items: [item]) {
    self = original
    self.items = items
  }
}

 

 

4️⃣ 바인딩..

let section = [
      CategorySectionModel(items: [Category.novel, Category.essay, Category.human]),
      CategorySectionModel(items: [Category.health, Category.social, Category.hobby]),
      CategorySectionModel(items: [Category.history, Category.religion, Category.home]),
      CategorySectionModel(items: [Category.language, Category.travel, Category.computer]),
      CategorySectionModel(items: [Category.magazine, Category.comic, Category.art]),
      CategorySectionModel(items: [Category.improve, Category.economy])
]
    
Observable.just(section)
      .bind(to: categoryCV.rx.items(dataSource: dataSource))
      .disposed(by: self.disposeBag)

넣고자 하는 섹션별로 구성된 CategorySectionModel의 배열을 section이라는 이름으로 만들어줬습니다.

첫번째 섹션에는 Category.novel, Category.essay, Category.human이라는 세개의 아이템을,

두번째 섹션에는 Category.health, Category.social, Category.hobby 라는 세개의 아이템을 넣겠다는 의미입니다 ! ..

 

 

5️⃣ 끝

그럼 이렇게 원하는 대로 섹션 당 원하는 개수의 셀만큼 구성할 수 있습니다 !

테이블뷰도 마찬가지로 구성하시면 됩니다 !

완성