Origami というところの Advent Calender 19日目の記事です。
本当は 12日目の記事だったはずなんですが、
旬だからという理由でここに交代をお願いされました↓
Amazon Dash Buttonで非常ベルみたいなことをやってみた
はじめに
OrigamiではSwift始めたときから、MVVM を取り入れ始めていましたが、
当初はReactiveCocoaいいんじゃね?っていう界隈の流れがありつつも、
Objective-C製からSwift製へ移行していたこともあり、
お手製のFRPっぽく書けるバイディングツールを作って使っていました。
ところが、Swiftアップデートのたびにあやしい動きを見せるReactiveCocoaにとってかわり
RxSwiftが古きから目覚め云々...
ということで、最近RxSwift使ってみています。
RxSwift.Variable を使ってみる
RxSwiftの中でもVariableというプロパティ監視する用のやつが
好きになれそうです。
(ReactiveCocoa でいうところの MutableProperty です)
var nameLabel: UILabel
var name: Variable<String> = Variable("dongri")
var disposeBag = DisposeBag()
func setBinding() {
name.asObservable().subscribe(onNext: { [weak self] in
// あたらしい値をLabelに反映
self?.nameLabel.text = $0
}).addDisposableTo(disposeBag)
}
func updateToVP() {
name.value = "takashi"
}
簡単な例ですが、updateToVP()で行なっている name.value = "takashi"
この代入を行うとあらかじめbindされたlistenerへイベントが発火されて
nameLabel のテキストが変更されます。
ごく一般的なリアクティブなアプローチです。
ただこの代入について、よく思うことがあり、
イベント発火しすぎるのを避ける為しばしば
こう書きたくなることがあります。
// 値に変更があったときだけ代入します
func updateToVP() {
let VPName = "takashi"
if name.value != VPName {
name.value = VPName
}
}
ただ、実際のViewModelではプロパティが多く、
代入に3行かけたくない。
ということでVariableを拡張してみます
拡張 & String制約
protocol StringConvertible {}
extension String: StringConvertible {}
extension Variable where Element: StringConvertible {
func assignIfNeeded(_ right: String) {
if let v = self.value as? String, v != right {
self.value = (right as? Element)!
}
}
}
わざわざStringConvertibleを定義するのは、
StringはConcreteTypeなため、Genericsの拡張に対して制約を課せないらしい。。
そのためProtocolTypeを作ってStringにimplementしてます。
その辺は、こちらが参考になりました。
https://lists.swift.org/pipermail/swift-evolution/Week-of-Mon-20160229/011666.html
http://stackoverflow.com/questions/39735753/swift-3-generic-extension-arguments
そのままString制約もいつかできようになるといいですね(切実)
上記の拡張を作っておくと、updateToVP() は以下のように書けるようになりました。
func updateToVP() {
name.assignIfNeeded("takashi")
}
これで値に変更があった場合のみ、イベントが飛ぶようになりました。
ただ、注意しなければいけないのは、Viewの生成のタイミング如何によって
思わぬところでイベントが飛んでこないというパターンが発生するので、
初期化時にすでに取得できている値をちゃんと入れておく等の処理が必要になります。
その辺はデータの持ち方によるのでよ〜く考えてカマしてみましょう。
12日目の記事のslack通知にもこのようなロジックが入れば、
DashButtonで通知が飛びすぎなくていいですね
We are hiring
多分採用されると思うから応募しようぜ
https://www.wantedly.com/companies/origami/projects