How to use RxSwift to draw the UICollectionView cells according to the number of data

35 Views Asked by At

I made a var sample = Public Subject <[]>() and I'm going to draw a vowel view with it. If the number of samples is 0, I would like to draw one collection View cell, and if it is more than one, I would like to draw according to the number of samples.

self.viewModel.sample
    .bind(to: collectionView.rx.items(
        cellIdentifier: "cell",
        cellType: Cell.self
    )) { index, item , cell in
        //
    }
    .disposed(by: disposeBag)

I only know how to implement it as above. What should I do?

This is my first time using RxSwift. I don't know what to do.

2

There are 2 best solutions below

0
Daniel T. On BEST ANSWER

The answer by @son is great and should be accepted. Just for completeness, I will post this answer for those who want to show an "Empty View" instead of a single cell.

The solution then is to give the table view a background view that represents what it looks like when empty, then you can do this:

items
    .bind(to: tableView.rx.items(cellIdentifier: "Cell")) { _, item, cell in
        cell.textLabel?.text = item
    }
    .disposed(by: disposeBag)

tableView.backgroundView = createEmptyView()

items
    .map { !$0.isEmpty }
    .bind(to: tableView.backgroundView!.rx.isHidden)
    .disposed(by: disposeBag)
0
son On

There are a few approaches for this circumstance:

  1. Handling the data: you can define multiple types within viewModel.sample, i.e placeholder or normal. In the case viewModel.sample is empty, you just need to append a placeholder, then toggle the cell's UI based on type.
enum DataType {
  case placeholder
  case normal
}

struct Sample {
  let type: DataType
  //Other stuff
}

viewModel.sample.bind... { index, item , cell in
  if item.type == .placeholder {
    ...
  else {
    ...
  }
}

  1. Or going back to data source style with RxTableViewDataSourceType.
final class SampleDataSource: NSObject, UITableViewDataSource, RxTableViewDataSourceType {
  private var models: [Sample] = []
  
  func tableView(_ tableView: UITableView, observedEvent: Event<[Sample]>) {
    switch observedEvent {
      case .next(let models):
        self.models = models
        tableView.reloadData()
      default: 
        break
    }
  }
  
  func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if models.isEmpty {
      let placeholerCell = ...
    } else {
      let cell = ...
    }
  }
  
  func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    models.isEmpty ? 1 : models.count
  }
}

Then bind viewModel.sample to this SampleDataSource:

viewModel.sample
  .bind(to: tableView.rx.items(dataSource: SampleDataSource()))
  .disposed(by: disposeBag)