ReactiveSwift Signal.Observerにbind出来るようになった🎉
SwiftでMVVMのViewModelを作るとき、Viewからの入力に関していえばViewModelでObservableを保持しそれをObserverとして公開するのが一般的だと思います。
final class ViewModel { private let tapLoginSubject = PublishSubject<Void>() var tapLogin: AnyObserver<Void> { return tapLoginSubject.asObserver() } }
ReactiveSwiftの標準の機能ではObserverに対してBindできないため、RxSwiftと同様にObserverに対してBindするにはExtensionを定義する必要がありました。
しかし10日ほど前にObserverに対してbindする機能が標準で搭載されるようになりました。
下記のextensionが追加されました。
extension Signal.Observer { @discardableResult public static func <~ <Source: BindingSource> (observer: Signal<Value, Error>.Observer, source: Source) -> Disposable? where Source.Value == Value { return source.producer.start { [weak observer] in switch $0 { case .value(let val): observer?.send(value: val) default: break } } } }
なのでViewModelを下のように定義して
final class ViewModel { struct Input { var tapLogin: Signal.Observer<Void> } let input: Input init() { let (tapLoginSignal, tapLoginObserver) = Signal<Void, Never>.pipe() input = Input( tapLogin: tapLoginObserver ) } }
こんな感じにBindすることができました。
viewModel.input.tapLogin <~ loginButton.reactive.controlEvent(.touchUpInside).map { _ in }
徐々にではありますがRxSwiftよりもReactiveSwift派になってきています。
自分がやりたかった機能が最新のバージョンで取り込まれるとということはなんか安心します(みんな似たよなことをやりたかったということなので)
※私はRxSwiftでの開発経験があるわけでもないし、ReactiveSwift歴も2週間程度です(ドキュメントは基本的に目を通しています)