티스토리 뷰
이렇게 준비를 한다..!
1. 뷰컨에 TableView를 올려주고
2. Tableview에 TableViewCell을 올려주고
3. TableViewCell의 identifier를 NameCell 로 설정해준다
그리고 RxTableViewController에 RxSwift와 RxCocoa를 import 하고 bind할 준비를 해준다
>> 총 4가지 방법으로 tableView를 그릴 수 있다
https://github.com/RxSwiftCommunity/RxDataSources 를 보면 다음과 같이 나와있다
Bind the data to the tableView/collectionView using one of:
rx.items(dataSource:protocol<RxTableViewDataSourceType, UITableViewDataSource>)
rx.items(cellIdentifier:String)
rx.items(cellIdentifier:String:Cell.Type:_:)
rx.items(_:_:)
[ 1 ] tableView.rx.items 사용하기
class RxTableViewController: UIViewController {
@IBOutlet weak var tableView: UITableView!
let bag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
bindTableView()
}
private func bindTableView() {
let cities = ["London", "Vienna", "Lisbon"]
let citiesOb: Observable<[String]> = Observable.of(cities)
citiesOb.bind(to: tableView.rx.items) { (tableView: UITableView, index: Int, element: String) -> UITableViewCell in
guard let cell = tableView.dequeueReusableCell(withIdentifier: "NameCell") else { return UITableViewCell() }
cell.textLabel?.text = element
return cell
}.disposed(by: bag)
}
}
[ 2 ] tableView.rx.items(cellIdentifier:String) 사용하기
private func bindTableView() {
let cities = ["London", "Vienna", "Lisbon"]
let citiesOb: Observable<[String]> = Observable.of(cities)
citiesOb.bind(to: tableView.rx.items(cellIdentifier: "NameCell")) { (index: Int, element: String, cell: UITableViewCell) in
cell.textLabel?.text = element
}.disposed(by: bag)
}
[ 3 ] tableView.rx.items(cellIdentifier: String, cellType: Cell.Type) 사용하기
이런 식으로 NameCell 클래스를 만들어주고
class NameCell: UITableViewCell {
}
private func bindTableView() {
let cities = ["London", "Vienna", "Lisbon"]
let citiesOb: Observable<[String]> = Observable.of(cities)
citiesOb.bind(to: tableView.rx.items(cellIdentifier: "NameCell", cellType: NameCell.self)) { (index: Int, element: String, cell: NameCell) in
cell.textLabel?.text = element
}.disposed(by: bag)
}
cell에 기본으로 있는 textLabel말고 프로퍼티를 만들어서 사용하여 보자 : )
class NameCell: UITableViewCell{
@IBOutlet weak var numberLabel: UILabel!
@IBOutlet weak var nameLabel: UILabel!
}
private func bindTableView() {
let cities = ["London", "Vienna", "Lisbon"]
let citiesOb: Observable<[String]> = Observable.of(cities)
citiesOb.bind(to: tableView.rx.items(cellIdentifier: "NameCell", cellType: NameCell.self)) { (index: Int, element: String, cell: NameCell) in
cell.numberLabel.text = "\(index)"
cell.nameLabel.text = element
}.disposed(by: bag)
}
[ 4 ] tableView.rx.items(dataSource:protocol<RxTableViewDataSourceType, UITableViewDataSource>) 사용하기
tableView 를 어떻게 표현할지 미리 지정한 datasource를 사용한 방법이다
pod으로 RxDataSource를 설치해주고 import 해준다
import RxDataSources
그 후 이 클래스로 만든 datasource를 사용할 것이다
open class RxTableViewSectionedReloadDataSource<S: SectionModelType>
: TableViewSectionedDataSource<S>
RxDataSources에서는 SectionModelType을 따르는 SectionModel을 이미 구현해놓았는데, 이것을 사용하면 된다
public struct SectionModel<Section, ItemType> {
public var model: Section
public var items: [Item]
public init(model: Section, items: [Item]) {
self.model = model
self.items = items
}
}
extension SectionModel
: SectionModelType {
public typealias Identity = Section
public typealias Item = ItemType
public var identity: Section {
return model
}
}
private func bindTableView() {
let cities = ["London", "Vienna", "Lisbon"]
let configureCell: (TableViewSectionedDataSource<SectionModel<String, String>>, UITableView,IndexPath, String) -> UITableViewCell = { (datasource, tableView, indexPath, element) in
guard let cell = tableView.dequeueReusableCell(withIdentifier: "NameCell", for: indexPath) as? NameCell else { return UITableViewCell() }
cell.textLabel?.text = element
return cell
}
let datasource = RxTableViewSectionedReloadDataSource<SectionModel<String, String>>.init(configureCell: configureCell)
datasource.titleForHeaderInSection = { datasource, index in
return datasource.sectionModels[index].model
}
let sections = [
SectionModel<String, String>(model: "first section", items: cities),
SectionModel<String, String>(model: "second section", items: cities)
]
Observable.just(sections)
.bind(to: tableView.rx.items(dataSource: datasource))
.disposed(by: bag)
}
이름이 너무 긴 것을 Typealias를 통해 줄여주고,
datasource 만드는 부분도 프로퍼티로 빼주고 코드를 정리하자 : )
typealias CitySectionModel = SectionModel<String, String>
typealias CityDataSource = RxTableViewSectionedReloadDataSource<CitySectionModel>
private func bindTableView() {
let firstCities = ["London", "Vienna", "Lisbon"]
let secondCities = ["Paris", "Madrid", "Seoul"]
let sections = [
SectionModel<String, String>(model: "first section", items: firstCities),
SectionModel<String, String>(model: "second section", items: secondCities)
]
Observable.just(sections)
.bind(to: tableView.rx.items(dataSource: cityDatasource))
.disposed(by: bag)
}
private var cityDatasource: CityDataSource {
let configureCell: (TableViewSectionedDataSource<CitySectionModel>, UITableView,IndexPath, String) -> UITableViewCell = { (datasource, tableView, indexPath, element) in
guard let cell = tableView.dequeueReusableCell(withIdentifier: "NameCell", for: indexPath) as? NameCell else { return UITableViewCell() }
cell.textLabel?.text = element
return cell
}
let datasource = CityDataSource.init(configureCell: configureCell)
datasource.titleForHeaderInSection = { datasource, index in
return datasource.sectionModels[index].model
}
return datasource
}
이렇게 section을 가진 tableview를 만들어줄 수 있다 : )
https://github.com/RxSwiftCommunity/RxDataSources
이 사이트를 가보면 Footer 넣기 등등 더 자세하게 알 수 있다 : )
******* 4가지 방법 비교 *************
[ 1 ] tableView.rx.items
[ 2 ] tableView.rx.items(cellIdentifier:String)
[ 3 ] tableView.rx.items(cellIdentifier: String, cellType: Cell.Type)
- 3번만 CellType으로 지정해준 한가지 Type의 Cell만 사용할 수 있음
ex) 1번 이런식으로 여러 cell 지정가능
viewModel.news.bind(to: tableView.rx.items) { (tableView, index, news) -> UITableViewCell in
if news.type == "" {
let cell = tableView.dequeueReusableCell(withIdentifier: "ShareTableViewCell") as? ShareTableViewCell
return cell ?? UITableViewCell()
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "FeedTableViewCell") as? FeedTableViewCell
return cell ?? UITableViewCell()
}
}.disposed(by: bag)
[ 4 ] tableView.rx.items(dataSource:protocol<RxTableViewDataSourceType, UITableViewDataSource>)
- 4번만 Section 사용가능하다
******* 꿀팁 *****************
.을 치고 .을 지우고 엔터를 누르면 클로저가 자동완성된다
이렇게 .을 지우고 엔터를 누르시오
+ UITableViewDelegate 도 사용해보자
viewdidload 에
tableView.rx.setDelegate(self).disposed(by: bag)
를 추가해주고
extension RxTableViewController: UITableViewDelegate {
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 100
}
}
Delegate 안의 필요한 메소드를 활용하여준다
옛날에 어떤 분께서 "Observable Event는 단방향이기 때문에 Delegate를 통해 값 가져오기가 불가능하다 이것이 rx를 이용한 tableView의 한계이다" 라고 말씀하셨는데 이 말을 이해하지는 못했다.
하지만 rx를 통해 tableView코드가 분산안되고 한눈에 들어오게 되는 점이 참 좋았는데 delegate는 rx쓰기 전과 동일한 방식으로 해줘야하는 것이 조~~~금 아쉬운 것 같다 🤔
'🍏 > RxSwift' 카테고리의 다른 글
[RxSwift] Subject / Relay / Driver / Variable (2) | 2019.04.04 |
---|---|
[RxSwift] Subject (0) | 2019.04.04 |
[RxSwift] Observable의 공유 (0) | 2019.04.04 |
[RxSwift] 예제로 이해하는 Delegate Proxy (4) | 2019.02.04 |
[Rxswift] RGB Slider로 View의 Color를 바꿔주기 (0) | 2018.07.24 |
- Total
- Today
- Yesterday
- 플러터 얼럿
- Flutter Clipboard
- flutter deep link
- Flutter getter setter
- github actions
- drf custom error
- 구글 Geocoding API
- ribs
- cocoapod
- Sketch 누끼
- Django FCM
- 장고 URL querystring
- Flutter Spacer
- DRF APIException
- flutter build mode
- Django Heroku Scheduler
- 플러터 싱글톤
- flutter dynamic link
- PencilKit
- Django Firebase Cloud Messaging
- Flutter 로딩
- Flutter Text Gradient
- Dart Factory
- 장고 Custom Management Command
- flutter 앱 출시
- Watch App for iOS App vs Watch App
- METAL
- ipad multitasking
- Python Type Hint
- SerializerMethodField
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 | 29 | 30 | 31 |