RxSwift) RxCocoa Binding
바인딩 에는 소비자와 생산자가 있습니다.
생산자는 Observable 입니다.
소비자는 UI Component 입니다.
Binder는 특별한 옵저버 입니다. 즉 데이터 소비자 입니다.
Observable → Binder
Binder는 옵저버이기에 새로운값을 전달할 수는 있지만 구독자를 추가할 수는 없습니다.
Observable → Next ✅ → Binder
Observable → Completed ✅ → Binder
Observable → Error ❌ → Binder
Binder는 Next 이벤트를 받으면 UI가 업데이트 됩니다.
Binder는 Error 이벤트를 받지 않습니다.
UI는 Main Thread에서 업데이트 되어야 합니다.
이제 UITextFiled 에 입력한 글씨는UILabel에 업데이트 해주겠습니다.
일반적으로 Delegate를 통해서 데이터를 UITextFiled 에 입력된 문자를 받아 UILabel에 적용시켜 주게 됩니다.
하지만 RxCocoa에서는 Binder를 통해 이것을 하게 됩니다.
Pods/Pods/RxCocoa/UITextField+Rx.swift 파일을 열어보면
extension Reactive where Base: UITextField {
public var text: ControlProperty<String?> {
value
}
... 이하 생략
이렇게 정의 되어있습니다.
ControlProperty 는 데이터를 바인딩할때 사용하는 특별한 옵저버블입니다.
즉, text 는 옵저버블입니다. 타입파라미터는 <String?> 입니다.
즉, UITextField가 업데이트 되면 String? 형식으로 Next이벤트를 방출합니다.
import UIKit
import RxSwift
import RxCocoa
class TestViewControler : UIViewController {
@IBOutlet weak var testLabel: UILabel!
@IBOutlet weak var testField: UITextField!
let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
testLabel.text = ""
testField.rx.text
.subscribe(onNext: { [weak self] str in
DispatchQueue.main.async {
self?.valueLabel.text = str
}
})
.disposed(by: disposeBag)
}
}
next이벤트를 통해 방출된 UITextField의 문자열을 받아 Main Thread 에서 업데이트 해줍니다.
모든 UI는 Main Thread에서 업데이트 되어야 합니다. 따라서 DispatchQueue 를 사용했는데 .observe(on:) 연산자를 이용하면 코드가 깔끔해집니다.
testField.rx.text
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] str in
self?.testLabel.text = str
})
.disposed(by: disposeBag)
여기서 더 나아가서 bind(to:) 연산지를 사용할 수 있습니다.
testField.rx.text
.bind(to: testLabel.rx.text)
.disposed(by: disposeBag)
bind(to:) 에 RxCocoa에서 확장된 UILabel.rx.text 옵저버블을 넣으면 구독됩니다.