RxSwift 用語解説

⚠️ 執筆時点の RxSwift バージョンは 3.4.1 です
RxSwift の基本的な用語に対しての大きな変更はあまり無いと思いますが、バージョンの違いによってちょっとインターフェイスが変わっているところがあるので注意してください。

# Overview
ReactiveExtension のざっくり説明と、RxSwift でよく使う用語のまとめです。
[文字リンク](#)はソースコード、[📖](#)はドキュメントへのリンクになっています。

# ReactiveExtension / RxSwift
## ReactiveExtension

  >ReactiveX is a combination of the best ideas from
the Observer pattern, the Iterator pattern, and functional programming
http://reactivex.io/

## RxSwift
- `Observable` (`ObservableType`) は実質 `Sequence`
- `Observable.subscribe` は実質 `Sequence.makeIterator`
- `Observer` は `Iterator` の `next()` を呼び出す代わりに `Observable` を `subscribe` することで `Sequence` の要素を受け取る

```swift
enum Event<Element>  {
    case next(Element)      // next element of a sequence
    case error(Swift.Error) // sequence failed with error
    case completed          // sequence terminated successfully
}

class Observable<Element> {
    func subscribe(_ observer: Observer<Element>) -> Disposable
}

protocol ObserverType {
    func on(_ event: Event<Element>)
}
```
https://github.com/ReactiveX/RxSwift/blob/3.4.1/Documentation/GettingStarted.md#basics

# Observable
## `subscribe`
`Observer` を渡すかクロージャを渡して `subscribe` する

```swift
someObservable
    .subscribe { event in
        switch event {
        case .next(let value):
            // do something
        case .error(let error):
            // handle error
        case .completed:
            // do something
        }
}
```

## Operators
`map`, `flatMap`, `filter`, `scan`, `take`, `merge`, `zip`, `concat`, ...

オペレータ一覧 [📖](http://reactivex.io/documentation/operators.html)

## Cold / Hot [📖](https://github.com/ReactiveX/RxSwift/blob/3.4.1/Documentation/HotAndColdObservables.md)
### Cold Observable
- `subscribe` されて初めてイベントが流れ出す
- `Observer` が `subscribe` する度に別々のストリームが生成される
- Async operations, HTTP Connections, TCP connections, streams

### Hot Observable
- `subscribe` されてなくてもイベントが流れている
- 一つのストリームを複数の `Observer` が `subscribe` できる
- Hot な `Observable` は `connect` するとイベントが流れ出す (`subscribe` されていようとされていまいと)
- RxSwift では [`ConnectableObservable`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/ConnectableObservable.swift) は Hot
- Variables / properties / constants, tap coordinates, mouse coordinates, UI control values, current time

## `publish` / `refCount` / `replay`
### [`publish`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/Multicast.swift#L45) [📖](http://reactivex.io/documentation/operators/publish.html)
- `Observable` を Hot (`ConnectableObservable`) に変換する
  - 内部的には `multicast` を呼んで `PublishSubject` (後述) に `Observable` をくっつけてる

### [`replay(n)`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/Multicast.swift#L62) [📖](http://reactivex.io/documentation/operators/replay.html)
- `Observable` を Hot (`ConnectableObservable`) に変換する
  - 内部的には `multicast` を呼んで `ReplaySubject` (後述) に `Observable` をくっつけてる
- `subscribe` するとこれまで流れていたイベントが n 個まとめて再度流れてくる

### [`refCount`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/Multicast.swift#L91) [📖](http://reactivex.io/documentation/operators/refcount.html)
- Hot な `Observable` を `RefCount` という `Observable` でラップする
- `RefCount` を `subscribe` するとラップされた Hot な `Observable` の `connect` が呼び出されて値が流れ出し、`RefCount` を `subscribe` している `Observer` がひとりも居なくなるとラップされた Hot な `Observable` が `dispose` される

### [`share`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/Multicast.swift#L107)
`publsh().refCount()`

### [`shareReplay(n)`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/ShareReplay1.swift#L21)
`replay(n).refCount()`

### [`shareReplayLatestWhileConnected`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Observables/ShareReplay1WhileConnected.swift#L23)
大体 `shareReplay(1)` と同じだけど `observer` が居なくなったら `replay` バッファをクリアするやつ

## Traits [📖](https://github.com/ReactiveX/RxSwift/blob/3.4.1/Documentation/Traits.md)
色々な Observable

### [Single](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Traits/PrimitiveSequence.swift#L21)
一度だけ `next` が流れてくるという決まりの `Observable` で、 `next` が来たらその後すぐ `copmleted` も流れてくる

```swift
public enum SingleEvent<Element> {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)

    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)
}
```

### [Completable](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Traits/PrimitiveSequence.swift#L31)
値を持った `next` は無く `completed` のみ流れてくる決まりの `Observable`

```swift
public enum CompletableEvent {
    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)

    /// Sequence completed successfully.
    case completed
}
```

### [Maybe](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Traits/PrimitiveSequence.swift#L26)
一度だけ `next` が流れてくる or `completed` のみ流れてくる決まりの `Observable`で、`next` が来たらその後すぐ `copmleted` も流れてくる

```swift
public enum MaybeEvent<Element> {
    /// One and only sequence element is produced. (underlying observable sequence emits: `.next(Element)`, `.completed`)
    case success(Element)

    /// Sequence terminated with an error. (underlying observable sequence emits: `.error(Error)`)
    case error(Swift.Error)

    /// Sequence completed successfully.
    case completed
}
```

### [Driver](https://github.com/ReactiveX/RxSwift/tree/3.4.1/RxCocoa/Traits/Driver) (RxCocoa)
- `Observer` の処理を `MainScheduler` で実行
- エラーは無視
- `shareReplayLatestWhileConnected()` する
- UI イベントを扱うのに使うとコードがスッキリする

`Observer.asDriver(onErrorJustReturn: [])` は下記と同じ

```swift
let safeSequence = someObservable
  .observeOn(MainScheduler.instance)       // observe events on main scheduler
  .catchErrorJustReturn(onErrorJustReturn) // can't error out
  .shareReplayLatestWhileConnected         // side effects sharing
return Driver(raw: safeSequence)           // wrap it up
```

### Relay (RxCocoa)
- replay しない Driver
- :point_right: [RxSwift 4 の Signal と Relay - Qiita](https://qiita.com/morishin/items/fbbb71d6b49f89d33b98)

### [ControlProperty](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxCocoa/Traits/ControlProperty.swift) / [ControlEvent](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxCocoa/Traits/ControlEvent.swift) (RxCocoa)
なんかこういうのもあります


# Subject [📖](http://reactivex.io/documentation/subject.html)
## [`PublishSubject`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Subjects/PublishSubject.swift)
- きほんの Subject
- 外からイベントを流せる Observable みたいなイメージ
- `Observer` を配列で持っている
- `PublishSubject#subscribe(observer)` で渡された `observer` を配列に加える
- `PublishSubject#on(event)` が呼ばれると抱えている `Observer` 達の `on` にイベントを渡す
- `subscribe` も `on` もあるので `ObserverType` であり `ObservableType` でもある

## [`ReplaySubject`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Subjects/ReplaySubject.swift)
- `subscribe(observer)` した時に新たに加わった `observer` にこれまでのイベントを全て流し直す

## [`BehaviorSubject`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Subjects/BehaviorSubject.swift)
- `ReplaySubject` が全てのイベントを流し直すのに対し、最後のイベントだけ流し直すやつ

## [`Variable`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Subjects/Variable.swift)
- `BehaviorSubject` をラップして `value` プロパティを生やしたやつ
- `Variable.value` を介して値を get / set できる

## [`AsyncSubject`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxSwift/Subjects/AsyncSubject.swift)
- `on(.completed)` が呼ばれたら最後に流れた `on(.next(value))` イベントのみ `Observer`
に流すやつ

# Signal (RxCocoa)
- Error と Complete が流れない Subject
- :point_right: [RxSwift 4 の Signal と Relay - Qiita](https://qiita.com/morishin/items/fbbb71d6b49f89d33b98)

# RxTest
## [`TestScheduler`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxTest/Schedulers/TestScheduler.swift)
仮想時間を持ってて `start` を呼ぶとガッと時間を進めてくれる

## [`TestableObservable`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxTest/TestableObservable.swift)
- `TestSchaduler` を受け取ってインスタンス化
- 仮想時間 `t` になったらイベント `e` が流れるという情報 ([`Recorded`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxTest/Recorded.swift)) の配列を内部に持っていて、scheduler の仮想時間を進めるとイベントを流してくれる

## [`TestableObserver`](https://github.com/ReactiveX/RxSwift/blob/3.4.1/RxTest/TestableObserver.swift)
- `TestSchaduler` を受け取ってインスタンス化
- 仮想時間を進めてイベントが流れてきたら時間とともにイベントを `Recorded` に詰めて配列に記録してくれる