⚠️ 執筆時点の 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
の要素を受け取る
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
されて初めてイベントが流れ出す -
Observer
がsubscribe
する度に別々のストリームが生成される - Async operations, HTTP Connections, TCP connections, streams
Hot Observable
-
subscribe
されてなくてもイベントが流れている - 一つのストリームを複数の
Observer
がsubscribe
できる - Hot な
Observable
はconnect
するとイベントが流れ出す (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 な
Observable
をRefCount
というObservable
でラップする -
RefCount
をsubscribe
するとラップされた Hot なObservable
のconnect
が呼び出されて値が流れ出し、RefCount
をsubscribe
しているObserver
がひとりも居なくなるとラップされた Hot なObservable
がdispose
される
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)
- replay しない Driver
- RxSwift 4 の Signal と Relay - Qiita
ControlProperty / ControlEvent (RxCocoa)
なんかこういうのもあります
Subject 📖
PublishSubject
- きほんの Subject
- 外からイベントを流せる Observable みたいなイメージ
-
Observer
を配列で持っている -
PublishSubject#subscribe(observer)
で渡されたobserver
を配列に加える -
PublishSubject#on(event)
が呼ばれると抱えているObserver
達のon
にイベントを渡す -
subscribe
もon
もあるのでObserverType
でありObservableType
でもある
ReplaySubject
-
subscribe(observer)
した時に新たに加わったobserver
にこれまでのイベントを全て流し直す
BehaviorSubject
-
ReplaySubject
が全てのイベントを流し直すのに対し、最後のイベントだけ流し直すやつ
Variable
-
BehaviorSubject
をラップしてvalue
プロパティを生やしたやつ -
Variable.value
を介して値を get / set できる
AsyncSubject
-
on(.completed)
が呼ばれたら最後に流れたon(.next(value))
イベントのみObserver
に流すやつ
Signal (RxCocoa)
- Error と Complete が流れない Subject
- RxSwift 4 の Signal と Relay - Qiita
RxTest
TestScheduler
仮想時間を持ってて start
を呼ぶとガッと時間を進めてくれる
TestableObservable
-
TestSchaduler
を受け取ってインスタンス化 - 仮想時間
t
になったらイベントe
が流れるという情報 (Recorded
) の配列を内部に持っていて、scheduler の仮想時間を進めるとイベントを流してくれる
TestableObserver
-
TestSchaduler
を受け取ってインスタンス化 - 仮想時間を進めてイベントが流れてきたら時間とともにイベントを
Recorded
に詰めて配列に記録してくれる