iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 9
0
Mobile Development

RxSwift / 30天探索之旅系列 第 9

第 9 天 - Filtering Observables

  • 分享至 

  • xImage
  •  

嗨!今天要講Filtering Observables,它能約束訂閱者收到的元素,感覺就很像是在Swift當中使用filter一樣,同樣的,Filtering實在太多種類了,這裡就介紹我常用或有趣的。

Filter

這個超常用,用法跟Swift的.filter一樣,給定條件,符合條件的才會發送給訂閱者,這邊我在.filter前後都加上.debug(),方便看出前後的不同,各位嘗試的時候可以使用emoji。

Observable.of(1, 2, 3, 4, 5)
    .debug("A")
    .filter { $0 % 2 == 1 }
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

結果如下,從列印的結果就能看到只有基數被發送出來

B -> subscribed
A -> subscribed
A -> Event next(1)
B -> Event next(1)
A -> Event next(2)
A -> Event next(3)
B -> Event next(3)
A -> Event next(4)
A -> Event next(5)
B -> Event next(5)
A -> Event completed
B -> Event completed
B -> isDisposed
A -> isDisposed

實際開發上,可能會遇到這種情境,MyResult類別中有code變數,他代表API回傳結果的各種狀況,我們需要在 code是A跟不是A的時候做不同的事情,也許我們就可以像下面這樣寫,先用.filter分成不同的condition,再去 transform或combine其他Observable,這部份過幾天就講到了!

let subject = PublishSubject<MyResult>()
let observer = subject.asObserver()
let observable = subject.asObservable()

let conditionA = observable.filter { $0.code == "A" }

let conditionB = observable.filter { $0.code != "A" }

conditionA.map { _ in neededDataA }

conditionB.map { _ in neededDataB }

skip

顧名思義它會略過一些元素,他有幾個很相似的operator,我們下面會放一起講

Observable.of(1, 2, 3, 4, 5)
    .skip(2)
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

列印結果如下

B -> subscribed
B -> Event next(3)
B -> Event next(4)
B -> Event next(5)
B -> Event completed
B -> isDisposed

skipWhile

定義『略過符合條件的元素,直到遇到不符合條件的元素(即 false),就停止略過』

Observable.of(1, 3, 5, 6, 7)
    .skipWhile { $0 % 2 == 1 }
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

結果如下

B -> subscribed
B -> Event next(6)
B -> Event next(7)
B -> Event completed
B -> isDisposed

skipUntil

定義『略過元素,直到另一個Observable發送元素,就停止略過』,跟前面兩種相比,前面兩種是靜態的設定過濾條件,skipUntil則是可以基於另一個Observable 去動態過濾元素。

let subject = PublishSubject<String>()
let trigger = PublishSubject<Void>()

subject
    .skipUntil(trigger)
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

subject.onNext("1")

subject.onNext("2")

trigger.onNext(())

subject.onNext("3")

subject.onNext("4")

結果會是這樣

B -> subscribed
B -> Event next(3)
B -> Event next(4)

說實在,我比較常用的只有skip,在某些情況下可能需要略過第一個元素,可以寫成.skip(1),但operator 就是多學一個,之後說不定就有機會用到了!

Take

takeskip就是相反的存在,前者是取的n個元素,後者是略過n個元素,同樣的,它也有takeWhiletakeUntil

除此之外,他還有一個takeLast,只取最後n個元素,下面就直接展示takeLast的範例程式,有興趣的人可以自己嘗試看看其他的。

Observable.of(1, 2, 3, 4, 5)
    .takeLast(2)
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

執行結果如下,只取最後 2 個元素

B -> subscribed
B -> Event next(4)
B -> Event next(5)
B -> Event completed
B -> isDisposed

DistinctUntilChanged

定義『排除重複的元素,直到不是重複時,才會發出』,比如下方範例,當true轉false時才會發送元素

Observable.of(true, true, false, false, true, false)
    .distinctUntilChanged()
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

執行結果

B -> subscribed
B -> Event next(true)
B -> Event next(false)
B -> Event next(true)
B -> Event next(false)
B -> Event completed
B -> isDisposed

你也可以制定重複的定義,像以下這樣,

Observable.of(1, 7, 3, 5, 9)
    .distinctUntilChanged { prev, curr in prev > curr }
    .debug("B")
    .subscribe()
    .disposed(by: disposeBag)

執行結果

B -> subscribed
B -> Event next(1)
B -> Event next(7)
B -> Event next(9)
B -> Event completed
B -> isDisposed

今天講了Filtering,明天會講Transforming,陸續這幾天會把operator大致了解過一遍,掰掰


上一篇
第 8 天 - 淺談Subject使用時機
下一篇
第 10 天 - Transforming Observables (上)
系列文
RxSwift / 30天探索之旅30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言