- RxSwift: Reactive Programming with Swift の読書メモです。この本を読んでみようかと思う人の参考になれば。
- 演習が充実している本ですが、その部分については割愛します。
Chapter 5: Filtering Operators
Ignoring operators
- ignoreElements
// protocol ObservableType
func ignoreElements() -> RxSwift.Observable<Self.E>
- elementAt
- 特定の順番の要素だけを取り出す
- http://reactivex.io/documentation/operators/elementat.html
// protocol ObservableType
func elementAt(_ index: Int) -> RxSwift.Observable<Self.E>
- filter
- クロージャで指定した条件を満たす要素だけを取り出す
- http://reactivex.io/documentation/operators/filter.html
// protocol ObservableType
func filter(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
Skipping operators
- skip
- 最初の n 個の要素を無視する
- http://reactivex.io/documentation/operators/skip.html
// protocol ObservableType
func skip(_ count: Int) -> RxSwift.Observable<Self.E>
- skipWhile
- クロージャで指定した条件が true の間要素を無視する。一度 false になったらそれ以降の要素を全て通過させる。
- クロージャに要素とそのインデクス番号が渡ってくる skipWhileWithIndex もある。
- http://reactivex.io/documentation/operators/skipwhile.html
// protocol ObservableType
func skipWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
- skipUnitl
- 別の observable から何か値が出力されるまでの間要素を無視する。
- http://reactivex.io/documentation/operators/skipuntil.html
Taking operators
- take
- 最初の n 個だけを取り出す
- http://reactivex.io/documentation/operators/take.html
// protocol ObservableType
func take(_ count: Int) -> RxSwift.Observable<Self.E>
- takeWhile
- クロージャで指定した条件が true の間要素を通過させる。一度 false になったら以降の要素を全て無視する。
- クロージャに要素とそのインデックス番号が渡ってくる takeWhileWithIndex もある。
- 本の takeWhilewithIndex のマーブル図はおかしい。
- http://reactivex.io/documentation/operators/takewhile.html
// protocol ObservableType
func takeWhile(_ predicate: @escaping (Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
- takeUntil
- 別の observable から何か値が出力されるまでの間要素を通過させる。
- 本文の最後の説明が ???
- http://reactivex.io/documentation/operators/takeuntil.html
// protocol ObservableType
func takeUntil<O>(_ other: O) -> RxSwift.Observable<Self.E> where O : ObservableType
Distinct operators
- distinctUntilChange
- 前の要素と値が変わった場合だけ値を出力する。
- Equatable に準拠した要素が = で比較するものとクロージャで比較条件を指定するものがある
- http://reactivex.io/documentation/operators/distinct.html
- 前の要素と値が変わった場合だけ値を出力する。
// protocol ObservableType where Self.E : Equatable
func distinctUntilChanged() -> RxSwift.Observable<Self.E>
// protocol ObservableType
func distinctUntilChanged(_ comparer: @escaping (Self.E, Self.E) throws -> Bool) -> RxSwift.Observable<Self.E>
chapter 6: Filtering Operators in Practice
Sharing subscriptions
- observable にオペレータを連ねただでけは実際には何もしない。末尾で subscribe() を呼んで初めて値の生成を行う。
- 通常 subscribe() を呼ぶ毎に新しい Observable が作られるが、それらが同じもので同じ値を返す保証はない。また同じ値を返すとしても生成コストが大きい場合がある。この場合 share() で作られる共有 Observable が使える。共有 Observable は参照カウンタを持っていて最初に subscribe される時に作られ全てのサブスクリプションから dispose() される時に破棄される。その後再度 subscribe される時には新しいインスタンスが作られる。
// protocol ObservableType
func share() -> RxSwift.Observable<Self.E>
- 指定した時間の間イベントを通過させ、そのあとに completed を送る。
// protocol ObservableType
func take(_ duration: RxTimeInterval, scheduler: SchedulerType) -> RxSwift.Observable<Self.E>
- throttle で一定期間入力を遅延させ、その間の最後の入力のみを出力させることができる。これによって短期間に 2 回タップしたを 1 回として扱ったり、インクリメンタルサーチできたりする。
- http://reactivex.io/documentation/operators/debounce.html
// protocol ObservableType
func throttle(_ dueTime: RxTimeInterval, latest: Bool = default, scheduler: SchedulerType) -> RxSwift.Observable<Self.E>
Chapter 7: Transforming Operators
Transforming elements
- toArray
- シーケンスの要素全てを単一の配列に変換する
- http://reactivex.io/documentation/operators/to.html
// protocol ObservableType
func toArray() -> RxSwift.Observable<[Self.E]>
- map
- シーケンスの各要素を指定のクロージャで変換する。
- その要素のインデックス番号も一緒にクロージャに渡ってくる mapWithIndex もある。
- http://reactivex.io/documentation/operators/map.html
// protocol ObservableType
func map<R>(_ transform: @escaping (Self.E) throws -> R) -> RxSwift.Observable<R>
func mapWithIndex<R>(_ selector: @escaping (Self.E, Int) throws -> R) -> RxSwift.Observable<R>
Transforming inner observables
- flatMap
- Observable (または Observable に変換可能な要素)のシーケンスから各 Observable の要素が全て流れてくるシーケンスを作る。
- 複数のシーケンスを一つのシーケンスにまとめる。
- 引数に渡すクロージャで Observable に変換可能な要素を Observable に変換する。もともと Observable ならそのまま返す。
- クロージャは各 Observable にごとに 1 回呼ばれる。各 Observalbe に値が流れて来るたびに呼ばれるわけではない。
- http://reactivex.io/documentation/operators/flatmap.html
// protocol ObservableType
func flatMap<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : ObservableConvertibleType
- flatMapLatest
- 元のシーケンス (Observable のシーケンス) に追加された最後の Observable から流れて来る要素だけを結果のシーケンスに流す。
- 一例としてはインテリセンスみたいなものを実装する際に使える。最新の入力仕掛けの文字列に対するサジェスチョンのみを表示したい場合、過去の入力仕掛けの文字列に対して非同期で返ってきたサジェスチョンを無視するのに使える。
- http://reactivex.io/documentation/operators/flatmap.html
// protocol ObservableType
func flatMapLatest<O>(_ selector: @escaping (Self.E) throws -> O) -> RxSwift.Observable<O.E> where O : ObservableConvertibleType
Chapter 8: Transforming Operators in Practice
- RxSwift はプラットフォームに依存しない純粋な Rx API を提供するのに対し、RxCocoa は UIKit と Cocoa に固有な機能を提供する。
- shareReply
- shareReply も共有 Observable を作るが、指定された個数の最後に送信された要素を保存している。新しく接続して来る observer に対してはその要素を渡す。
- http://reactivex.io/documentation/operators/replay.html
// protocol ObsevableType
func shareReplay(_ bufferSize: Int) -> RxSwift.Observable<Self.E>
Chapter 9: Combining Operators
Prefixing and concatenating
- startWith
- シーケンスに初期値を持たせる。subscribe すると必ず最初にその値が渡って来るようになる。
- concat の 1 要素版と考えることもできる。
- http://reactivex.io/documentation/operators/startwith.html
// protocol ObservableType
func startWith(_ elements: Self.E...) -> RxSwift.Observable<Self.E>
- concat
- 完了する複数のシーケンスを繋げる。まず最初のシーケンスの要素が出力され、完了したあとに次のシーケンスの要素が出力され、その完了後に 3 番目のシーケンスが...と続く。
- いずれかのシーケンスがエラーになると concat の結果のシーケンスもエラーになる。
- http://reactivex.io/documentation/operators/concat.html
// static method
// class Observable
static func concat<S: Sequence >(_ sequence: S) -> Observable<Element> where S.Iterator.Element == Observable<Element>
static func concat<S: Collection >(_ collection: S) -> Observable<Element> where S.Iterator.Element == Observable<Element>
static func concat(_ sources: Observable<Element> ...) -> Observable<Element>
// instance method
// protocol ObservableType
func concat<O>(_ second: O) -> RxSwift.Observable<Self.E> where O : ObservableConvertibleType, O.E == Self.E
Merging
- merge
- 複数のシーケンスから単一のシーケンスを作る。入力シーケンスのいずれかの値が変化した時にその値が出力シーケンスの値として出力される。
- 元になった全てのシーケンスが終了するとそのシーケンスも終了する。
- 元になったシーケンスのいずれかが終了するとそのシーケンスも終了する。
- 同時にサブスクライブするシーケンスの最大数を制限できる変種がある。
- http://reactivex.io/documentation/operators/merge.html
// protocol ObservableType where Self.E : ObservableConvertibleType
func merge() -> RxSwift.Observable<Self.E.E>
func merge(maxConcurrent: Int) -> RxSwift.Observable<Self.E.E>
Combining elements
- combineLatest
- 複数のシーケンスから単一のシーケンスを作る。入力シーケンスのいずれかの値が変化した時に、各入力シーケンスの最新の値を引数に取るクロージャが実行されその結果が出力シーケンスの値となる。
- 全ての入力シーケンスから最初の値が入って来るまで出力シーケンスに値は出力されない。
- 各入力シーケンスの値が独立した引数としてクロージャに渡って来る変種とそれらを一つの配列に詰め込んで渡って来る変種がある。
- http://reactivex.io/documentation/operators/combinelatest.html
// class Observable
static func combineLatest<O1: ObservableType, O2: ObservableType>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> E) -> Observable<E>
static func combineLatest<C: Collection>(_ collection: C, _ resultSelector: @escaping ([C.Iterator.Element.E]) throws -> Element) -> Observable<Element> where C.Iterator.Element: ObservableType
- zip
- 複数の入力シーケンスから単一のシーケンスを作る。入力シーケンスの全ての値が変化した時に、各入力シーケンスの値を引数に取るクロージャが実行されその結果が出力シーケンスの値となる。
- 全ての入力シーケンスの値が変化するまで出力シーケンスに新しい値は出力されない。
- http://reactivex.io/documentation/operators/zip.html
// class Observable
static func zip<O1: ObservableType, O2: ObservableType>(_ source1: O1, _ source2: O2, resultSelector: @escaping (O1.E, O2.E) throws -> E) -> Observable<E>
Triggers
- trigger
- トリガーとなる observable にイベントが発生した時にデータソースとなる observable のデータを出力する。
- http://reactivex.io/documentation/operators/combinelatest.html
// extension ObservableType
func withLatestFrom<SecondO>(_ second: SecondO) -> RxSwift.Observable<SecondO.E> where SecondO : ObservableConvertibleType
- sample
- trigger の変種でトリガーとなるデータソースにイベントが発生し、かつ、データソースのデータが前回と変わっていた場合だデータを出力する。
- trigger とはトリガーとデータソースの指定が逆になっているので注意。
- http://reactivex.io/documentation/operators/sample.html
// protocol ObservableType
func sample<O>(_ sampler: O) -> RxSwift.Observable<Self.E> where O : ObservableType
Switches
- amb
- 二つの observable のうち、最初に値を出力した方の値だけを出力する。
- http://reactivex.io/documentation/operators/amb.html
// protocol ObservableType
func amb<O2>(_ right: O2) -> RxSwift.Observable<Self.E> where O2 : ObservableType, O2.E == Self.E
- switchLatest
- 複数のシーケンスのうち、動的に指定したシーケンスの値だけを出力する。指定はいつでも変えられる。
- http://reactivex.io/documentation/operators/switch.html
// protocol ObservableType where Self.E : ObservableConvertibleType
func switchLatest() -> RxSwift.Observable<Self.E.E>
Combining elements within a sequence
- reduece
- 標準の reduce の observable sequence 版。
- sequence が完了した時に値が出力されることに注意。
- http://reactivex.io/documentation/operators/reduce.html
// protocol ObservableType
func reduce<A>(_ seed: A, accumulator: @escaping (A, Self.E) throws -> A) -> RxSwift.Observable<A>
- scan
- reduce とほぼ同じ。
- 新しい値が入力され、再計算される度に値が出力される点が reduce と異なる。
- reduce, scan はステートを持つので上手に使うと変数を使わずに済ませられるかも
- http://reactivex.io/documentation/operators/scan.html
// protocol ObservableType
func scan<A>(_ seed: A, accumulator: @escaping (A, Self.E) throws -> A) -> RxSwift.Observable<A>
Chapter 10: Combining Operators in Practice
(演習なので割愛)
Chapter 11: Time Based Operators
Buffering operators
- replay
- 指定の数の最新の要素を保持しておき、新しく接続してきた Observer にはまずそれを渡す。それ以後は入力から渡って来る要素をそのまま渡す。
- replyAll は全ての要素を保持する。
- 戻り値である ConnectableObservable は subscribe するだけではイベントを発行せず、connect() が呼ばれて初めて発行する。
- http://reactivex.io/documentation/operators/replay.html
// protocol ObservableType
func replay(_ bufferSize: Int) -> RxSwift.ConnectableObservable<Self.E>
- buffer
- 入力データのバッファリングを行う。
- バッファは指定されたサイズの要素を保持することができる。
- 入力されたデータは一旦バッファに保存する。
- バッファリング時間の間新たな要素の入力がなかったらバッファに溜まっているデータを全て配列として出力する。
- バッファに保持できる以上のデータの入力あった場合は即座にバッファの中の最も古いデータを出力し、新しいデータをバッファに保持する。
- 新たなデータがなかった場合でもバッファリング時間毎に要素 0 個の配列を出力する。
- http://reactivex.io/documentation/operators/buffer.html
- 入力データのバッファリングを行う。
// protocol Observabletype
func buffer(timeSpan: RxTimeInterval, count: Int, scheduler: SchedulerType) -> Observable<[E]>
- window
- buffer とほぼ同じだが、buffer は一定周期またはバッファが一杯になる毎に要素の配列を返すのに対し、windows は要素を出力する Observable を返す。
- 一定周期またバッファが一杯になる度に出力先の Observable を変更する。
- http://reactivex.io/documentation/operators/window.html
// protocol ObservableType
func window(timeSpan: RxTimeInterval, count: Int, scheduler: SchedulerType) -> RxSwift.Observable<RxSwift.Observable<Self.E>>
Time-shifting operators
- delay
// protocol ObservableType
func delay(_ dueTime: RxTimeInterval, scheduler: SchedulerType) -> Observable<E>
- delaySubscription
- サブスクリプションの開始を遅延させる。
- delay は全ての要素の出力を遅延させるのに対し delaySubscription はサブスクリプションの開始のみを遅延させる。サブスクリプション開始前に入力された値は失われる。
- サブスクリプション開始後は入力が遅延なしで出力させる。
- http://reactivex.io/documentation/operators/delay.html
// protocol ObservableType
func delaySubscription(_ dueTime: RxTimeInterval, scheduler: SchedulerType) -> Observable<E>
Time Operators
- interval
- 一定時間毎に値を出力する Observable を作る。
- 値は符号付き整数で 0 からインクリメントしていく。
- 最初の値も period だけ待ってから出力される。
- http://reactivex.io/documentation/operators/interval.html
// class Observable where Element : SignedInteger
static func interval(_ period: RxTimeInterval, scheduler: SchedulerType) -> Observable<E>
- timer
- 一定時間毎に値を出力する Observable を作る。
- 値は符号付き整数で 0 からインクリメントしていく。
- dueTime は最初のイベント発行までの時間。
- period はその後のイベントの発行間隔。nil だとワンショットになる。
- http://reactivex.io/documentation/operators/timer.html
// class Observable where Element: SignedInteger
static func timer(_ dueTime: RxTimeInterval, period: RxTimeInterval? = nil, scheduler: SchedulerType) -> Observable<E>
- timeout
- 一定時間入力がなかった場合にエラーイベント(RxError.timeoutError)を発行する。
- エラーイベントを発行するのではなく、入力元を別の Observable に切り替える変種もある。
- http://reactivex.io/documentation/operators/timeout.html
// protocol ObservableType
func timeout(_ dueTime: RxTimeInterval, scheduler: SchedulerType) -> Observable<E>
func timeout<O: ObservableConvertibleType>(_ dueTime: RxTimeInterval, other: O, scheduler: SchedulerType) -> Observable<E> where E == O.E