前置き
UIViewControllerとViewModelとをバインディングする正攻法の試行錯誤をメモしておく
結論は出てません
パターン1
古来より伝わるIBAction
これだとPresenterの感じがする
class ViewModel {
func buttonDidTap() {
}
}
class ViewController: UIViewController {
let viewModel: ViewModel = ViewModel()
@IBAction func buttonDidTap(_ sender: Any) {
self.viewModel.buttonDidTap()
}
}
パターン2
ボタンから直接ViewModelのメソッドを呼び出す
class ViewModel {
@objc func buttonDidTap(_ sender: Any) {
}
}
class ViewController: UIViewController {
let viewModel: ViewModel = ViewModel()
@IBOutlet weak var button: UIButton! {
didSet {
self.button.addTarget(self.viewModel,
action: #selector(buttonDidTap(_:)),
for: UIControl.Event.touchUpInside)
}
}
}
パターン3 RxSwift
RxSwiftを使ったバインド
import RxCocoa
class ViewModel {
let buttonDidTap: PublishRelay<Void> = {
let relay: PublishRelay<Void> = PublishRelay<Void>()
relay.subscribe(onNext: {
})
return relay
}()
}
import RxSwift
class ViewController: UIViewController {
let viewModel: ViewModel = ViewModel()
@IBOutlet weak var button: UIButton! {
didSet {
self.button.rx.tap.bind(to: self.viewModel.buttonDidTap)
}
}
}
パターン4 ReactiveSwift
import ReactiveSwift
import ReactiveCocoa
class ViewModel {
let buttonDidTap: CocoaAction<UIButton> = CocoaAction<UIButton>(Action<Void, Any, Never>(execute: {
return .empty
}))
}
import ReactiveCocoa
class ViewController: UIViewController {
let viewModel: ViewModel = ViewModel()
@IBOutlet weak var button: UIButton! {
didSet {
self.button.reactive.pressed = self.viewModel.buttonDidTap
}
}
}
パターン5 RxSwift + Action
RxSwiftを使ったバインド
import Action
import RxCocoa
class ViewModel {
let buttonDidTap = CompletableAction<Void> { _ in
return Observable<Never>.empty().asCompletable()
}
}
import Action
import RxSwift
class ViewController: UIViewController {
let viewModel: ViewModel = ViewModel()
@IBOutlet weak var button: UIControl! {
didSet {
self.button.rx.bind(
to: self.viewModel.buttonDidTap,
controlEvent: self.button.rx.controlEvent(UIControl.Event.touchUpInside),
inputTransform: { _ in () }
)
}
}
}