2021. 8. 24. 16:35ㆍDeveloper.TokkiSea/Apple
TableView.rx
기존 방식이라면 UIViewController에 TableView 하나 추가
delegate와 dataSource를 UIViewController에 연결하고
UITableViewDelegate, UITableViewDataSource 를
상속한 다음
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath)
를 오버라이딩 한후
UITableViewCell 추가하고 클래스를 만들어 연결하고..
과정을 생략할 수 있습니다.
그냥 UITableView 추가하고 IBOutlet만 연결한 후
아래 코드를 작성하면 5개의 Cell 이 생성됩니다.
.bind()
내부적으로 subscribe를 사용하고 onNext 만 처리합니다.
Observable<[...]> 만 입력 가능해 보입니다.
@IBOutlet var tableView: UITableView!
var disposeBag = DisposeBag()
func bindTableView() {
let alphaBet = Observable.of(["A", "B", "C", "D", "E"])
alphaBet.bind(to: tableView.rx.items) { (tableView: UITableView, index: Int, element: String) in
let cell = UITableViewCell(style: .default, reuseIdentifier: "cell")
cell.textLabel?.text = element
return cell
}.disposed(by: disposeBag)
}
// A, B, C, D, E 가 적혀있는 Cell 이 생성된다.
// 다중 셀
enum MyModel {
case textEntry(String)
case pairOfText(String, String)
}
func bindTableView() {
let observable = Observable<[MyModel]>.just([
.textEntry("A"),
.pairOfText("B", "C"),
.textEntry("D"),
.pairOfText("E","F")
])
observable.bind(to: tableView.rx.items) { (tableView: UITableView, index: Int, element: MyModel) in
let indexPath = IndexPath(item: index, section: 0)
switch element {
case .textEntry(let txt1):
let cell = tableView.dequeueReusableCell(withIdentifier: "oneTextCell", for: indexPath) as! oneTextCell
cell.one.text = txt1
return cell
case .pairOfText(let txt2, let txt3):
let cell = tableView.dequeueReusableCell(withIdentifier: "twoTextCell", for: indexPath) as! twoTextCell
cell.two.text = txt2
cell.three.text = txt3
return cell
}
}.disposed(by: disposeBag)
}
TableView.rx.modelSelected
셀을 선택
tableView.rx.modelSelected(String.self)
.subscribe(onNext: { model in
print("\(model) was selected")
})
.disposed(by: disposeBag)
// 선택한 알파벳 String
- modelSelected(_:), modelDeselected(_:), itemSelected, itemDeselected
- itemAccessoryButtonTapped
- itemInserted, itemDeleted, itemMove (셀 editMode에서)
- willDisplayCell, didEndDisplayingCell.....
등 기존에 사용하던 UITableViewDelegate 함수들 이름 사용.
.drive()
subscribe의 UI(Main Thread)용
기존 subscribe로 OnSubscribe(Thread...) 식으로 사용해도 무관합니다.
let usernameValid = textField1.rx.text.asDriver().map { $0!.utf8.count > 0 }
let passwordValid = textField2.rx.text.asDriver().map { $0!.utf8.count > 0 }
let credentialsValid: Driver<Bool> =
Driver.combineLatest(usernameValid, passwordValid) { $0 && $1 }
credentialsValid.drive(onNext: { [weak self] valid in
print("ok enable login Button")
})
.disposed(by: disposeBag)
.orEmpty
위의 코드의 첫 번째 두 번째를 보면 $0에! 표가 붙어 있습니다.
map으로 들어오는 값이 optional이라서 그렇다.
nil이라도 들어오면 크래시가 납니다.
.orEmpty를 붙여주면 optional이 제거되어서 !를 제외해도 되고
nil 이면 "" 이 리턴됩니다.(이 코드에서는 그럴리는 없지만!!)
let usernameValid = textField1.rx.text.orEmpty.asDriver().map { $0.utf8.count > 0 }
let passwordValid = textField2.rx.text.orEmpty.asDriver().map { $0.utf8.count > 0 }
let credentialsValid: Driver<Bool> =
Driver.combineLatest(usernameValid, passwordValid) { $0 && $1 }
credentialsValid.drive(onNext: { [weak self] valid in
print("ok enable login Button")
})
.disposed(by: disposeBag)