LoginSignup
69

More than 3 years have passed since last update.

RxSwift 用語解説

Last updated at Posted at 2017-05-11

⚠️ 執筆時点の 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
  • ObserverIteratornext() を呼び出す代わりに Observablesubscribe することで Sequence の要素を受け取る
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>)
}

Observable

subscribe

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

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, ...

オペレータ一覧 📖

Cold / Hot 📖

Cold Observable

  • subscribe されて初めてイベントが流れ出す
  • Observersubscribe する度に別々のストリームが生成される
  • Async operations, HTTP Connections, TCP connections, streams

Hot Observable

  • subscribe されてなくてもイベントが流れている
  • 一つのストリームを複数の Observersubscribe できる
  • Hot な Observableconnect するとイベントが流れ出す (subscribe されていようとされていまいと)
  • RxSwift では ConnectableObservable は Hot
  • Variables / properties / constants, tap coordinates, mouse coordinates, UI control values, current time

publish / refCount / replay

publish 📖

  • Observable を Hot (ConnectableObservable) に変換する
    • 内部的には multicast を呼んで PublishSubject (後述) に Observable をくっつけてる

replay(n) 📖

  • Observable を Hot (ConnectableObservable) に変換する
    • 内部的には multicast を呼んで ReplaySubject (後述) に Observable をくっつけてる
  • subscribe するとこれまで流れていたイベントが n 個まとめて再度流れてくる

refCount 📖

  • Hot な ObservableRefCount という Observable でラップする
  • RefCountsubscribe するとラップされた Hot な Observableconnect が呼び出されて値が流れ出し、RefCountsubscribe している Observer がひとりも居なくなるとラップされた Hot な Observabledispose される

share

publsh().refCount()

shareReplay(n)

replay(n).refCount()

shareReplayLatestWhileConnected

大体 shareReplay(1) と同じだけど observer が居なくなったら replay バッファをクリアするやつ

Traits 📖

色々な Observable

Single

一度だけ next が流れてくるという決まりの Observable で、 next が来たらその後すぐ copmleted も流れてくる

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

値を持った next は無く completed のみ流れてくる決まりの Observable

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

    /// Sequence completed successfully.
    case completed
}

Maybe

一度だけ next が流れてくる or completed のみ流れてくる決まりの Observableで、next が来たらその後すぐ copmleted も流れてくる

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 (RxCocoa)

  • Observer の処理を MainScheduler で実行
  • エラーは無視
  • shareReplayLatestWhileConnected() する
  • UI イベントを扱うのに使うとコードがスッキリする

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

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)

ControlProperty / ControlEvent (RxCocoa)

なんかこういうのもあります

Subject 📖

PublishSubject

  • きほんの Subject
  • 外からイベントを流せる Observable みたいなイメージ
  • Observer を配列で持っている
  • PublishSubject#subscribe(observer) で渡された observer を配列に加える
  • PublishSubject#on(event) が呼ばれると抱えている Observer 達の on にイベントを渡す
  • subscribeon もあるので ObserverType であり ObservableType でもある

ReplaySubject

  • subscribe(observer) した時に新たに加わった observer にこれまでのイベントを全て流し直す

BehaviorSubject

  • ReplaySubject が全てのイベントを流し直すのに対し、最後のイベントだけ流し直すやつ

Variable

  • BehaviorSubject をラップして value プロパティを生やしたやつ
  • Variable.value を介して値を get / set できる

AsyncSubject

  • on(.completed) が呼ばれたら最後に流れた on(.next(value)) イベントのみ Observer に流すやつ

Signal (RxCocoa)

RxTest

TestScheduler

仮想時間を持ってて start を呼ぶとガッと時間を進めてくれる

TestableObservable

  • TestSchaduler を受け取ってインスタンス化
  • 仮想時間 t になったらイベント e が流れるという情報 (Recorded) の配列を内部に持っていて、scheduler の仮想時間を進めるとイベントを流してくれる

TestableObserver

  • TestSchaduler を受け取ってインスタンス化
  • 仮想時間を進めてイベントが流れてきたら時間とともにイベントを Recorded に詰めて配列に記録してくれる

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
69