하나의 TableView안에
위처럼
다양한 CellType을 적용해야할 때가 존재해요
그럴때 RxDataSource를 이용해서는 어떻게 처리하나~
에대해서 한번 알아보겠습니다
먼저 CellModel을 만들어볼거에요
// MARK: - Cell Model
struct TestSection {
var items: [Item]
}
enum TestItem {
case aCell(ACellModel)
case bCell(BCellModel)
case none
}
extension TestSection: SectionModelType {
typealias Item = TestItem
init(original: TestSection, items: [Item] = []) {
self = original
self.items = items
}
}
struct ACellModel {
let string: String
}
struct BCellModel {
let string: String
}
Section이 Item배열을 가지고있고
Item은 enum타입으로 이루어져있어요
enum타입이 곧 Cell의 타입을 구분하기 위함이죠
다음으로
datasource를 정의해줄거에요
items이 [TestItem]타입이니까
item으로 TestItem이나올거고
enum타입이니까 구분해서 사용하면돼요
class RxDataSourceViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
private let disposeBag = DisposeBag()
private lazy var dataSource = RxTableViewSectionedReloadDataSource<TestSection> { [weak self] dataSource, tableview, indexPath, item in
switch item {
case let .aCell(cellModel):
let cell = tableview.dequeueReusableCell(withIdentifier: TestTableViewCell.identifier, for: indexPath) as! TestTableViewCell
return cell
case let .bCell(cellModel):
let cell = tableview.dequeueReusableCell(withIdentifier: TestTableViewCell.identifier, for: indexPath) as! TestTableViewCell
return cell
case .none:
let cell = tableview.dequeueReusableCell(withIdentifier: TestTableViewCell.identifier, for: indexPath) as! TestTableViewCell
return cell
}
}
private let data = BehaviorRelay<[TestSection]>(value: [])
...
}
aCell, bCell, none타입에 맞게
원하는 Cell클래스를 만들어서 넣어주면 구분할 수있어요
간단하게 여기서는 하나의 셀로만 구분해서 사용해보도록 할거에요
어떻게만들어서 적용할지
샘플 데이터를 생성해볼게요
override func viewDidLoad() {
super.viewDidLoad()
/* cell register 해줘야합니다 */
tableView.rowHeight = UITableView.automaticDimension
let item1 = TestItem.aCell(ACellModel(string: "1"))
let item2 = TestItem.aCell(ACellModel(string: "2"))
let item3 = TestItem.aCell(ACellModel(string: "3"))
let item4 = TestItem.bCell(BCellModel(string: "4"))
let item5 = TestItem.none
let section1 = TestSection(items: [item1, item2, item3, item4, item5])
data
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
data.accept([section1])
}
/* cell구성
a
a
a
b
none
*/
한 section에 필요한 item만큼 넣어서 생성해줬구요
추가적으로
cell의 이벤트를 받아오는 작업을 해보려고해요
방법으로
delegate를 사용하는방법
클로져사용하는 방법
rx extension을 사용하는 방법
이 있을 것같네요
rx답게 사용하기위해 rx를 이용해볼거구요
간단한 동작을 구현해볼거에요
Cell안에 버튼이있고
버튼을 누르면 버튼의 크기를 +20씩 늘릴거에요
하지만 이렇게 늘리기만하면 적용이안돼서
Cell크기가 그대로일거니까
이벤트를 전달해서 ViewController에 업데이트하는 코드도 추가할거에요
class TestTableViewCell: UITableViewCell {
static let identifier = "TestCell"
@IBOutlet weak var heightLayout: NSLayoutConstraint!
@IBOutlet weak var button: UIButton!
private let disposeBag = DisposeBag()
func bind() {
// 버튼클릭시 크기 +20, 버튼타이틀을 크기숫자로 변경
button.rx.tap
.subscribe(onNext: { [weak self] in
let height: CGFloat = (self?.heightLayout.constant ?? 0) + 20
print(height)
self?.heightLayout.constant = height
self?.button.setTitle("\(height)", for: .normal)
})
.disposed(by: disposeBag)
}
func aCell() {
button.setTitle("ACell", for: .normal)
}
func bCell() {
button.setTitle("BCell", for: .normal)
}
func noneCell() {
button.setTitle("NoneCell", for: .normal)
}
}
// Rx
extension Reactive where Base: TestTableViewCell {
var tapButton: ControlEvent<Void> {
ControlEvent(events: base.button.rx.tap)
}
}
이 셀의 이벤트를 실행하기위해
datasource코드를 조금 수정해야겠네요
private lazy var dataSource = RxTableViewSectionedReloadDataSource<TestSection> { [weak self] dataSource, tableview, indexPath, item in
switch item {
case let .aCell(cellModel):
let cell = tableview.dequeueReusableCell(withIdentifier: TestTableViewCell.identifier, for: indexPath) as! TestTableViewCell
cell.bind()
cell.aCell()
cell.rx.tapButton
.subscribe(onNext: {
tableview.performBatchUpdates(nil)
})
return cell
...
}
초기상태는 ACell 텍스트가 뜨고
버튼을 누를때마다 크기+20가 되면서 텍스트에 버튼크기가 노출됩니다
cell.rx.tapButton -> 위에서 extension해서 이렇게 이벤트를 뷰컨트롤러에서 컨트롤할 수 있습니다!
'iyOmSd > Title: RxSwift' 카테고리의 다른 글
[RxSwift] Filtering Operators (0) | 2021.09.08 |
---|---|
[RxSwift] ReactorKit 체험 (Hello ReactorKit) (0) | 2021.03.25 |
[RxSwift] Observable? Driver? Relay? 알아보기 (0) | 2020.10.28 |
[RxSwift] bind, subscribe, drive (1) | 2020.10.03 |
[RxSwift] Observable, Subject, Relay (0) | 2020.06.27 |