RxSwiftでBindTo可能な独自プロパティを生やす方法
2018-01-13 13:25 - 1 min readMVVM的なアーキテクチャを採用しようとしたとき,KRProgressHUD
のような簡単にLoadingViewを出せるライブラリを使っていると,そのViewのOn/Offの制御をどうしようかと少し悩みます。ViewModelのOutputを普通にSubscribeして制御しても良いですが,できればRxCocoaで拡張されたUIView同様,BindToで見た目を制御したいです。
そこで,そもそもBindToをどうやって実現しているのか本家ソースコードを除くと一目瞭然で,Binder
というコンポーネントを利用すれば良いことがわかりました。ObservableのbindにBinderを渡してやることで他のUIViewと同様,自動的にsubscribeしてくれます。
具体的な使い方として,たとえばUIViewControllerに以下のようなextensionを定義してあげると良さげです。 以下の例におけるComputedPropertyのloadingViewはBindTo可能なプロパティを定義している本家コードほぼそのまま持ってきています。 第一引数で渡したインスタンスが,クロージャの第一引数へ,クロージャの第二引数に渡ってくる値が入っています。
extension UIViewController {
func showLoadingView() {
KRProgressHUD.show()
}
func hideLoadingView() {
KRProgressHUD.dismiss()
}
var loadingView: Binder<Bool> {
return Binder(self) {(vc, value: Bool) in
value ? vc.showLoadingView() : vc.hideLoadingView()
}
}
}
これで,なんの違和感もなくBindできました。
class TestViewController: UIViewController {
private let disposeBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
// ローディングViewを一定間隔でOnOffさせる。
Observable<Int>
.interval(1.0, scheduler: MainScheduler.instance)
.scan(true) { current, _ in !current }
.take(3)
.bind(to: self.loadingView)
.disposed(by: self.disposeBag)
}
}
ちなみにUILabelのその他のプロパティも本家の定義と同様にextensionを定義してやることで,Bindableにすることができます。