こんにちは、ガチエリアS帯のリードエンジニアの田村(@Utmrer)です。他のルールもS帯にいくため、Splatoon2サントラを聴きながら日々コーディングをしております。
この記事はConnehito Advent Calendar 2017の4日目の記事です。
今日はRxSwiftのコードを覗いていたら気づいたことを書きました。
(2017年12月4日現在の情報です)
Variableとは
VariableはRxSwiftで提供されているBehaviorSubjectのwrapperで値の取り出しや代入を直感的に扱うことができるSubjectの1つです。
MVVMでステートフルなViewModelのpropertyとして使っている人が多いのではないでしょうか。
// Example class VM { let name = Variable("") } class VC { func f() { textField.rx.text.orEmpty .bind(to: vm.name) .disposed(by: disposeBag) } }
RxSwift4でVariableはしれっとdeprecatedに
ある日RxSwift repositoryのコードを読んでいたらDeprecated.swiftという非推奨のAPIをまとめたファイルを見つけ、Variableが記載されているのを見つけました。
Warningが出ていないので気づけなかったのですが、Warningを出していないのは利用者が多いことなどが理由のようです。*1
ではVariableが非推奨になった時代に私たちはどうすればいいのでしょう。
安全なBehaviorSubjectであるBehaviorRelay
Variableのdeprecatedと同時に追加されたBehaviorRelayはBehaviorSubjectのwrapperでerrorの流れることが無い、安全なBehaviorSubjectです。この点においてVariableとほぼ同じ特性を持ちます。
Variableではvalue
propertyのsetter/getterで値の操作を行っていたのが、BehaviorRelayでは下記のようなaccept()
methodとvalue
propertyでアクセスします。
let relay = BehaviorRelay<Int>(value: 0) relay.asDriver() .drive(onNext: { value in print(value) }) .disposed(by: disposeBag) relay.accept(1) print(relay.value)
Variableが非推奨になったので、同様の性質をもつBehaviorRelayに移行していくのが正道となるでしょう。
BehaviorRelayはRxCocoa
今までVariableはRxSwift moduleの一部でしたが、BehaviorRelayはRxCocoa moduleの一部になっています。BehaviorRelayと同時期に実装された安全なPublishSubjectであるPublishRelayもRxCocoaです。
これは「Relayは特定の環境で求められるものであり、Reactive Extensionsのコンセプト外である」というのが理由のようです。*2
ではRxCocoaに含まれるのが適切なのでしょうか?RelayにはCocoaへの依存はありません。ちなみに、これらRelayの設計元になったと思われるRxJavaのRxRelayはRxJavaのユーティリティという立ち位置でRxJava, RxAndroidには実装されていません。
このままRxCocoaに含まれていくような気がしますが、RxRelayとして分離されることがあるかもしれません。
BehaviorRelayへの移行はやるべき?
今すぐにでもVariableからBehaviorRelayへの移行を行うべきか、というと個人的にはちょっと待とうと思っています。なぜならば、Variableで提供されていたbind(to:)
というmethodがまだBehaviorRelayには提供されていないからです。*3
RxSwiftの中の人も「ちゃんと移行方法を決めたら@availability
付けて本当にdeprecatedにするよ」と言っているのでそれまで待ってもいいかなと思っています。*4
下記のようにextensionを書くことでbind(to:)
を使うこともできるので待てなくなったら移行します。(副作用がちょっとわからないのでまだやってないのですが)
extension BehaviorRelay: ObserverType { public func on(_ event: Event<Element>) { switch event { case .next(let value): accept(value) default: break } } }
まとめ
以上、RxSwift4でのVariableとBehaviorRelayについてでした。@availability
が付くと大量のwarningが出る可能性があるので備えておきたいですね。
明日は@fortkleによるファビュラスマックスな5日目の記事をお送りします。