swift
RxDataSources
motosw3600
2022. 5. 7. 17:02
RxDataSources
- TableView, CollectionView를 Section을 사용해서 정의가능한 프레임워크
- Rx를 사용한 반응형 데이터 적용
- cellForRowAt을 사용하지 않고 cell데이터 지정
- Link
Section정의
RxDataSource에 사용될 DataType은 SectionModelType을 준수
items는 cell데이터 타입 등록
struct SectionOfMain {
var items: [Item]
}
extension SectionOfMain: SectionModelType {
typealias Item = MainCellData
init(original: Self, items: [Item]) {
self = original
self.items = items
}
}
CellData정의
Section안에 정의한 item enumType으로 설정
(cellType은 TableView cell register부분에서 한번에 등록하기 위한 변수)
enum MainCellData {
case main(title: String, isFocus: Bool)
case sub(title: String)
var cellType: MainCellDataProtocol.Type {
switch self {
case .main: return MainCell.self
case .sub: return SubCell.self
}
}
}
protocol MainCellDataProtocol: AnyObject {
func apply(item: MainCellData) // data 적용
static func cellHeight(item: MainCellData) -> CGFloat // 동적 height설정
}
Cell정의
위에서 정의한 MainCellDataProtocol을 준수하는 Cell정의
class MainCell: UITableViewCell, MainCellDataProtocol {
let titleLabel: UILabel = {
let label = UILabel()
label.text = "main"
label.textColor = .purple
label.font = .systemFont(ofSize: 20)
return label
}()
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
contentView.addSubview(titleLabel)
titleLabel.snp.makeConstraints { make in
make.center.equalToSuperview()
}
}
required init?(coder: NSCoder) {
super.init(coder: coder)
}
func apply(item: MainCellData) {
guard case let .main(title, isFocus) = item else { return }
titleLabel.text = title
titleLabel.font = isFocus ? .boldSystemFont(ofSize: 20) : .systemFont(ofSize: 20)
}
static func cellHeight(item: MainCellData) -> CGFloat {
return 70
}
}
TabelView RxDataSource적용
// dataSource선언
private var dataSource: RxTableViewSectionedReloadDataSource<SectionOfMain>?
private func setupDataSource() {
// dataSource정의 (기존 tableView(_: cellForRowAt.. 부분)
let dataSource = RxTableViewSectionedReloadDataSource<SectionOfMain> {
_, tableView, indexPath, item in
let cellId = String(describing: item.cellType)
tableView.register(item.cellType, forCellReuseIdentifier: cellId)
tableView.register(item.cellType, forCellReuseIdentifier: cellId)
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
(cell as? MainCellDataProtocol)?.apply(item: item)
return cell
}
self.dataSource = dataSource
// viewModel의 sections binding
viewModel.sections
.observe(on: MainScheduler.instance)
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
github linkg: https://github.com/motosw3600/RxDataSourceEx