【Swift】RxSwiftをTwitterで知り合った人に教えてもらったPart2

#はじめに
[前回](https://qiita.com/REON/items/f4a938bcc1f41fe106c7)
今回も教えていただいたことをまとめていこうと思います。

#実装

```swift:ViewController
import UIKit
import RxSwift
import RxCocoa

final class ViewController: UIViewController {
    
    @IBOutlet private weak var textField: UITextField!
    @IBOutlet private weak var button: UIButton!
    @IBOutlet private weak var label: UILabel!
    private let disposeBag = DisposeBag()
    private var viewModel: ViewModelType = ViewModel()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // MARK: - Input
        //bindでViewModelにイベントを送るパターン
        textField.rx.text.orEmpty
            .bind(to: viewModel.inputs.text)
            .disposed(by: disposeBag)
        
        //onNextで送るパターン
        button.rx.tap
            .subscribe { _ in
                self.viewModel.inputs.text.onNext("タップ")
            }
            .disposed(by: disposeBag)
        
        // MARK: - Output
        //viewModelからoutputをUIパーツにbindするパターン
        viewModel.outputs.validText
            .bind(to: label.rx.text)
            .disposed(by: disposeBag)
        
    }
    
}
```

```swift:ViewModel 
import RxSwift
import RxCocoa

protocol ViewModelInput {
    //読み取り専用にしたいため、AnyObserver
    var text: AnyObserver<String> { get }
}

protocol ViewModelOutput {
    //ViewでsubsrcibeするためにObservable
    var validText: Observable<String> { get }
}

protocol ViewModelType {
    var inputs: ViewModelInput { get }
    var outputs: ViewModelOutput { get }
}

class ViewModel: ViewModelInput, ViewModelOutput {
    var text: AnyObserver<String>
    var validText: Observable<String>
    init() {
        let _validText = PublishRelay<String>()
        self.validText = _validText.asObservable()
        self.text = AnyObserver<String>() { text in
            //viewからイベントを受け取り、加工したものをoutputにaccept
            let validText = text.element!
            _validText.accept(validText)
        }
    }
}

extension ViewModel: ViewModelType {
    var inputs: ViewModelInput {
        return self
    }
    var outputs: ViewModelOutput {
        return self
    }
}
```

#イベントの送り方受け取り方
###Input(View -> ViewModel)
今回はボタンを押した時とテキストフィールドに文字が入力された時にイベントを流します。

以下はbindでviewModelのinputのtextにイベントを送っています。

```swift
textField.rx.text.orEmpty
    .bind(to: viewModel.inputs.text)
    .disposed(by: disposeBag)
```

こちらはボタンのイベントをviewModelのinputのtextにonNextで送っています。

```swift
button.rx.tap
    .subscribe { _ in
        self.viewModel.inputs.text.onNext("タップ")
    }
    .disposed(by: disposeBag)
```

そして、ViewModelのViewModelInputプロトコルに送るtextを定義しておいて、加工してoutputで返すという流れです。

```swift
protocol ViewModelInput {
    var text: AnyObserver<String> { get }
}
```

###Output(ViewModel -> View)
イニシャライザ内で値を加工し、acceptでoutputにイベントを送ります。

```swift
class ViewModel: ViewModelInput, ViewModelOutput {
    var text: AnyObserver<String>
    var validText: Observable<String>
    init() {
        let _validText = PublishRelay<String>()
        self.validText = _validText.asObservable()
        self.text = AnyObserver<String>() { text in
            let validText = text.element!
            _validText.accept(validText)
        }
    }
}
```

viewModelから送られてきたoutputをbindすることで、labelに反映させる。

```swift
viewModel.outputs.validText
    .bind(to: label.rx.text)
    .disposed(by: disposeBag)
```

#おわりに
少しずつ分かってきましたね！