【iOS, RxSwift】RxSwift入門〜オブザーバーパターンのイメージ〜

RxSwiftの入門に際して、まずはオブザーバーパターンを知る必要があります。
ここでは、そのイメージを掴むことを目的としています。



## オブザーバーパターンのイメージ
<img width="333" alt="オブザーバーパターンのイメージ" src="https://qiita-image-store.s3.amazonaws.com/0/138735/0f420fd2-0501-b7ae-3ce2-b4165b525297.png">

登場人物

* Observable（監視されるもの）
* Subscribe（それを購読するもの）
* イベント

## Observable（監視されるもの）
名前の通り監視可能なものを表すクラスがObservableです。
Observableのイメージは川です。
イベントとしてonNext, onError,  onComplete が流れてきます。

* onNext
デフォルトのイベント
イベント内に値を格納でき、何度でも呼びせる

* onError
エラーイベント
1度だけ呼ばれ、そのあとはイベントが発生しない

* onCompleted
完了イベント
1度だけ呼ばれ、そのあとはイベントが発生しない


<img width="340" alt="Observable（監視されるもの）" src="https://qiita-image-store.s3.amazonaws.com/0/138735/b6727853-a0ca-a984-3708-8feb7f5e8564.png">


## Subscribe（購読する）
イベントを受け取る側は subscribe メソッドでイベントの購読を行います。
Observableを作成することで川ができ、Subscribeでそこに流れてくるイベントを拾うイメージです。

<img width="337" alt="Subscribe（購読する）" src="https://qiita-image-store.s3.amazonaws.com/0/138735/50f273b9-774d-a441-a60d-6a3a961dd3e6.png">


## イベントを通知する
ObservableとSubscribe により、川とそこに流れるイベントを拾う準備ができました。
あとはそこにイベントを流せばイベントの発生〜受け取りまでの一連の流れができます。

<img width="333" alt="イベントを通知する" src="https://qiita-image-store.s3.amazonaws.com/0/138735/c47e4888-82f0-d21e-92cc-c7956b408e25.png">


## Dispose（購読を破棄する）
Disposeは購読を解除(破棄)するためのクラスで、dispose()メソッドを呼ぶことで明示的に購読を破棄するものです。
ObservableをSubscribeしている場合、onError/onCompleted が発生してイベントが終了すると購読解除状態になります。

では購読しているオブジェクト自身が解放されるときはどうでしょうか？
この場合、dispose()メソッドを呼んで購読を解除をしないとずっとメモリを消費してしまい、メモリリークを招きます。
そこで、DisposeBag()という入れ物にインスタンスを格納しておいて、デストラクタで一気に全部disposeする。その役割を担ってくれるのがDisposeBagです。
DisposeBag は Dispose インスタンスを貯め、自身が解放(deinit)され たときに管理している購読を全て自動で解放(unsubscribe)します。

ここまでが基本的なオブザーバーパターンの概要です。

<img width="403" alt="オブザーバーパターンの概要" src="https://qiita-image-store.s3.amazonaws.com/0/138735/7e1ff1a0-1d99-5088-16a6-ac7a50986647.png">



例えば、以下のようなコードを見てみましょう。

```.swift
hogeButton.rx.tap  // ← observable, タップした時にイベントを発生
    .subscribe { [unowned self] _ in // ← 購読
        // ボタンタップ時の処理
    }
    .disposed(by: disposeBag) // 
```

```rx.tap```や```rx.text``` といったものはRxSwifが提供している<font color="DeepPink">Observable</font>であり、例えば```rx.tap```であればタップのタイミングで<font color="DeepPink">イベントが発生</font>されます。
```.subscribe```によりタップ時のイベントが<font color="DeepPink">購読</font>されており、その時の処理を記述します。
そして最後に```.disposed```を記述することで購読の破棄が行われるようになっています。

## 【参考】 Obervable と Observerについて

### Observable
Observableは名前の通りobserveが可能なものです。
Observableからデータを受け取るにはsubscribe(observer)メソッドを呼びます。このメソッドは引数にObserverのインスタンスを取ります。

RxSwiftでは以下のように定義されています。

```.swift
/// A type-erased `ObservableType`. 
///
/// It represents a push style sequence.
public class Observable<Element> : ObservableType {
    /// Type of elements in sequence.
    public typealias E = Element
    
    init() {
#if TRACE_RESOURCES
        let _ = Resources.incrementTotal()
#endif
    }
    
    public func subscribe<O: ObserverType>(_ observer: O) -> Disposable where O.E == E {
        rxAbstractMethod()
    }
    
    public func asObservable() -> Observable<E> {
        return self
    }
    
    deinit {
#if TRACE_RESOURCES
        let _ = Resources.decrementTotal()
#endif
    }

    // this is kind of ugly I know :(
    // Swift compiler reports "Not supported yet" when trying to override protocol extensions, so ¯\_(ツ)_/¯

    /// Optimizations for map operator
    internal func composeMap<R>(_ transform: @escaping (Element) throws -> R) -> Observable<R> {
        return _map(source: self, transform: transform)
    }
}
```

### Observer 
Observableからのデータを受け取るためのクラスです。（流れてくるデータを observeするものです。）
onNext, onError, onCompletedが<font color="DeepPink">Observableにより</font>呼び出されます。

RxSwiftでは以下のように定義されており、データを受け取るためにメソッドが定義されていることがわかります。

```.swift
// Observableからのデータを受け取るものとしてObserverTypeプロトコルを定義
/// Supports push-style iteration over an observable sequence.
public protocol ObserverType {
    /// The type of elements in sequence that observer can observe.
    associatedtype E

    // オブザーバーにイベントを送るためのメソッドを定義
    /// Notify observer about sequence event.
    ///
    /// - parameter event: Event that occurred.
    func on(_ event: Event<E>)
}

/// Convenience API extensions to provide alternate next, error, completed events
extension ObserverType {
　
    // Observableにより呼び出されるメソッドを定義

    /// Convenience method equivalent to `on(.next(element: E))`
    ///
    /// - parameter element: Next element to send to observer(s)
    public func onNext(_ element: E) {
        on(.next(element))
    }
    
    /// Convenience method equivalent to `on(.completed)`
    public func onCompleted() {
        on(.completed)
    }
    
    /// Convenience method equivalent to `on(.error(Swift.Error))`
    /// - parameter error: Swift.Error to send to observer(s)
    public func onError(_ error: Swift.Error) {
        on(.error(error))
    }
}
```