지금 까지 기본적인 입출력만 binding 하는것을 해봤어요
약간 더 어려운
Rx를 이용한 TableView를 구현해 볼거에요
앞의 내용을 하면서 Rx를 조금이라도 이해 했다면 그리 많이 어렵지 않을 거에여!!
우선
Pod을 추가해주세요
많은 레퍼런스를 보면 이런 방식은 똑같이 하더라구요
그래서 저도 똑같이 했어요
Cell에 들어갈 데이터 타입을 정해야겠죠?
AnimatableSectionModelType 이건 음... 잘모르겠지만 SectionModel로 사용하기위해서
상속받아 사용하는 거같아요...
상속을 받으면 Identity과 Item를 정의하는게 나올거에요!!
Item은 테이블안에 들어갈 데이터의 타입으로 하고
identity는 연산 프로퍼티로 바꿨어요
MySection타입 객체 하나가 섹션 하나가 될거에요
header는 섹션의 title느낌
items는 섹션의 row느낌 입니다!!
이렇게 해주면 테이블뷰에 들어갈 데이터타입정의가 끝났어요!!
이제 Rx로 TableView를 구현해볼게요
저는 Xib파일로 TableViewCell를 생성했어요
아래는 DataSource를 정의 하는 코드입니다
configureCell의 파라미터로 4가지가 들어오고
그파라미터를 이용해서 보통 TableView의 DataSource를 정의하듯이 하면되요
섹션에 글자도 달아줄 수 있고
오른쪽 인디케이터쪽에 섹션단어를 보여줄 수 있어요
딜리게이트를 사용하기위해 설정해주고
‼️데이터 바인딩 해주기‼️
위의코드는 viewDidLoad위에 초기화한 클래스 맴버변수 입니다!!
subject에 data를 넣어두고 변하면 reload되는 형식이에요
지금까지 써왔던 BehaviorSubject와는 달리
이번에는 BehaviorRelay를 사용해요!!
뭐가다르냐면...
Relay는 Subject를 Wrapping한 녀석이에요...! 라고 써있어요
error와 complete가 없어요!!
dispose될때까지 계속 작동한다는 얘기죠
UI이벤트를 사용하는경우에 Relay가 적합하다고 하네요
함수의 차이도 있어요
onNext대신 accept를 이용해요
버튼을 누를때 마다 추가되도록
배열에 값을 추가하고 accept를 시켜서 갱신되도록 구현했어요
셀마다 크기를 다르게 하기위해서
앞에서 사용한 dataSource를 이용해서 셀높이를 조절했어요
여기까지 간단하게 RxDataSource로 기본적인 TableView를 만들었어요!!!
아래는 전체코드입니다!!
import UIKit
import RxCocoa
import RxSwift
import RxDataSources
struct MySection {
var header: String
var items: [Item]
}
// section Model
extension MySection: AnimatableSectionModelType {
typealias Item = Int
init(original: MySection, items: [Int]) {
self = original
self.items = items
}
var identity: String {
return header
}
}
class ViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
@IBOutlet weak var random: UIButton!
let disposeBag = DisposeBag()
var dataSource: RxTableViewSectionedReloadDataSource<MySection>!
var sections = [
MySection(header: "A", items: [1, 2, 3]),
MySection(header: "B", items: [4, 5])
]
private var subject: BehaviorRelay<[MySection]> = BehaviorRelay(value: [])
override func viewDidLoad() {
super.viewDidLoad()
// tableView 정의
let nib = UINib(nibName: "TestTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "TestCell")
// dataSource 정의
let dataSource = RxTableViewSectionedReloadDataSource<MySection>(
configureCell: { dataSource, tableView, indexPath, item in
let cell = tableView.dequeueReusableCell(withIdentifier: "TestCell", for: indexPath) as! TestTableViewCell
cell.selectionStyle = .none
cell.testLabel?.text = "Item \(item)"
return cell
})
// 처음값 초기화
subject.accept(sections)
//섹션 문자
dataSource.titleForHeaderInSection = { ds, index in
return ds.sectionModels[index].header
}
//오른쪽 인디케이터 문자
dataSource.sectionIndexTitles = { ds in
return ds.sectionModels.map { $0.header }
}
//오른쪽 인디케이터 문자와 인덱스참조가능
dataSource.sectionForSectionIndexTitle = { ds, title, index in
print(title)
print(index)
return ds.sectionModels.map { $0.header }.firstIndex(of: title) ?? 0
}
self.dataSource = dataSource
// delegate 사용을 위한 선언
tableView.rx.setDelegate(self)
.disposed(by: disposeBag)
// binding
subject
.bind(to: tableView.rx.items(dataSource: dataSource))
.disposed(by: disposeBag)
}
@IBAction func randomAction(_ sender: Any) {
sections.append(MySection(header: "C", items: [6, 7, 8]))
sections.append(MySection(header: "D", items: [4, 5]))
subject.accept(sections)
}
}
extension ViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
guard let item = dataSource?[indexPath], dataSource?[indexPath.section] != nil else { return 0.0 }
return CGFloat(40 + item * 10)
}
}
'iyOmSd > Title: RxSwift' 카테고리의 다른 글
[RxSwift] TableView 구현하기 (0) | 2020.06.05 |
---|---|
[RxSwift] Combine Operator정리 - CombineLatest, Merge, Zip (0) | 2020.05.30 |
[RxSwfit 기초] 원의 이동에따른 색변화 시키기 (0) | 2019.08.12 |
[RxSwift 기초] 검색창 결과 바로보기 - 예제로 RxSwift익히기 (0) | 2019.08.06 |
[RxSwift 기초] 로그인창을 입력에 따른 반응으로 구현하기 (0) | 2019.08.04 |