TableView
기존 UITableView를 통해 데이터를 표시하는 구조를 RxCocoa를 사용하여 구현해보도록 하겠습니다
우선 TableView에 보여줄 리스트 형태의 데이터를 Observable
로 변경합니다.
1
2
var nameList = appleProducts.map { $0.name }
var productList = appleProducts
1
2
let nameObservable = Observable.of(appleProducts.map { $0.name })
let productObservable = Observable.of(appleProducts)
DataSource
UITableViewDataSource
를 따로 구현하지 않고items
메소드로 간단하게 셀을 등록할 수 있습니다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
// #1
nameObservable
.bind(to: listTableView.rx.items) { (tableView, row, element) in
let cell = tableView.dequeueReusableCell(withIdentifier: "standardCell")!
cell.textLabel?.text = element
return cell
}
.disposed(by: bag)
// #2
nameObservable
.bind(to: listTableView.rx.items(cellIdentifier: "standardCell")) { row, element, cell in
cell.textLabel?.text = element
}
.disposed(by: bag)
// #3
productObservable
.bind(to: listTableView.rx.items(
cellIdentifier: "productCell",
cellType: ProductTableViewCell.self)
) { [weak self] row, element, cell in
cell.categoryLabel.text = element.category
cell.productNameLabel.text = element.name
cell.summaryLabel.text = element.summary
cell.priceLabel.text = self?.priceFormatter.string(for: element.price)
}
.disposed(by: bag)
Delegate
tableView:didSelectRowAtIndexPath:
대신 itemSelected
, modelSelected
를 사용하여 셀 선택 이벤트를 구현합니다.
var itemSelected: ControlEvent<IndexPath>
- 셀을 선택 할 때마다
IndexPath
를 가지고 있는next
이벤트를 방출
1
2
3
4
5
listTableView.rx.itemSelected
.subscribe(onNext: { [weak self] indexPath in
self?.listTableView.deselectRow(at: indexPath, animated: true)
})
.disposed(by: bag)
func modelSelected<T>(_ modelType: T.Type) -> ControlEvent<T>
modelSelected
은IndexPath
가 아니라 실제 모델 데이터를 방출
1
2
3
4
5
listTableView.rx.modelSelected(Product.self)
.subscribe(onNext: { product in
print(product.name)
})
.disposed(by: bag)
zip
메소드를 활용하여 modelSelected
, itemSelected
를 병합하여 모델 데이터와 인덱스를 한꺼번에 방출할 수 있습니다.
1
2
3
4
5
6
Observable.zip(listTableView.rx.modelSelected(Product.self), listTableView.rx.itemSelected)
.bind { [weak self] (product, indexPath) in
self?.listTableView.deselectRow(at: indexPath, animated: true)
print(product.name)
}
.disposed(by: bag)
만약 기존처럼 tableView.delegate = self
로 Delegate
를 지정해 준다면 RxCocoa
의 Delegate
메소드는 더이상 동작하지 않습니다.
기존의 UITableViewDelegate
를 RxCocoa
와 같이 사용하고 싶다면 아래와 같이 Delegate
를 지정해 줘야 합니다.
1
2
listTableView.rx.setDelegate(self)
.disposed(by: bag)
CollectionView
CollectionView
의 구현도 TableView
와 비슷합니다.
리스트 형태의 데이터를 Observable
로 변경하고 CollectionView
에 바인딩 해 줍니다
1
let colorObservable = Observable.of(MaterialBlue.allColors)
DataSource
UICollectionViewDataSource
를 따로 구현하지 않고 items
메소드로 간단하게 셀을 등록할 수 있습니다.
1
2
3
4
5
6
7
colorObservable
.bind(to: listCollectionView.rx
.items(cellIdentifier: "colorCell", cellType: ColorCollectionViewCell.self)) { index, color, cell in
cell.backgroundColor = color
cell.hexLabel.text = color.rgbHexString
}
.disposed(by: bag)
Delegate
collectionView:didSelectItemAtIndexPath:
대신 itemSelected
, modelSelected
를 사용하여 셀 선택 이벤트를 구현합니다.
var itemSelected: ControlEvent<IndexPath>
- 셀을 선택 할 때마다
IndexPath
를 가지고 있는next
이벤트를 방출
1
2
3
4
5
listCollectionView.rx.itemSelected
.subscribe(onNext: { index in
print("\(index.section) \(index.row)")
})
.disposed(by: bag)
func modelSelected<T>(_ modelType: T.Type) -> ControlEvent<T>
modelSelected
은IndexPath
가 아니라 실제 모델 데이터를 방출
1
2
3
4
5
listCollectionView.rx.modelSelected(UIColor.self)
.subscribe(onNext: { color in
print(color.rgbHexString)
})
.disposed(by: bag)
TableView
와 동일하게 기존의 UICollectionViewDelegate
, UICollectionViewDelegateFlowLayout
를 RxCocoa
와 같이 사용하고 싶다면 아래와 같이 Delegate
를 지정해 줘야 합니다.
1
2
listCollectionView.rx.setDelegate(self)
.disposed(by: bag)