前言
萬丈高樓平地起,前面兩篇地基已經(jīng)建好,現(xiàn)在開始第一層。
示例代碼請(qǐng)移步Github
RxSwift 4.4
從本篇開始接下來幾篇文章會(huì)詳細(xì)學(xué)習(xí) RxSwift 中 Operators,作為 Rx編程的基石,可以使用它來轉(zhuǎn)換,處理和響應(yīng)事件。
Operators 分為四個(gè)部分:
-
Filtering Operators:過濾 -
Transforming Operators: 轉(zhuǎn)換 -
Combing Operators: 組合 -
Time-Based Operators: 基于時(shí)間操作
接下來學(xué)習(xí)過濾相關(guān)的操作。
Filtering Operators
過濾操作分為四類:
| 分類 | 主要方法 | 說明 |
|---|---|---|
Ignoring Operators |
ignoreElements elementAt filter
|
用于忽略一些元素 |
Skipping Operators |
skip skipWhile skipUntil
|
|
Taking Operators |
take takeWhile takeUntil
|
|
Distinct Operators |
distinctUntilChange distinctUntilChanged(_:)
|
從整體上了解要學(xué)習(xí)的內(nèi)容,接下來詳細(xì)分析各個(gè)操作作用,特點(diǎn)及區(qū)別聯(lián)系。
Ignoring Operators
ignoreElements
特點(diǎn):忽略所有的 .next 事件元素,允許終止事件通過。如:.completed 和 .error。是不是應(yīng)該想起來什么?ignoreElements 實(shí)際上返回一個(gè) Completable。

raywenderlich.com
①:表示源序列,可以被訂閱
②:表示操作及參數(shù)
③:訂閱
實(shí)例代碼:
/// 1. ignoreElements : 忽略所有的 .next 事件元素,允許停止事件通過,如 .completed 和 .error.
/// 也許會(huì)發(fā)現(xiàn):ignoreElements 實(shí)際上返回一個(gè) Completable
example(of: "ignoreElements") {
// 1. 創(chuàng)建 subject
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
// 2. 添加訂閱
strikes
.ignoreElements() // 忽略所有元素
.subscribe{_ in
print("You are out!")
}
.disposed(by: disposeBag)
strikes.onNext("X") // 無輸出
strikes.onNext("Y") // 無輸出
strikes.onCompleted() // 輸出 You are out!
}
elementAt
特點(diǎn): 獲取指定位置的元素。只要獲取到指定位置的元素,訂閱就終止。

raywenderlich.com
示例代碼:
/// 2. elementAt : 獲取指定位置的元素。
/// 只要獲取到指定位置的元素,訂閱就終止。
example(of: "elementAt") {
let strikes = PublishSubject<String>()
let bag = DisposeBag()
strikes
.elementAt(2) // 獲取序列中 index = 2 的元素
.subscribe(onNext: { element in
print("\(element) - You are out!")
})
.disposed(by: bag)
strikes.onNext("X") // 無輸出
strikes.onNext("Y") // 無輸出
strikes.onNext("Z") // index = 2 輸出
// 輸出:Z - You are out!
}
filter
特點(diǎn):ignoreElement 和 elementAt 過濾序列元素。有時(shí)不針對(duì)全部或單個(gè)元素操作。filter 提供了一個(gè)閉包,針對(duì)所有的元素,只要滿足添加就可以輸出。

raywenderlich.com
示例代碼:
/// 3. ignoreElement 和 elementAt 過濾序列元素。有時(shí)不針對(duì)全部或單個(gè)元素操作。
/// filter 提供了一個(gè)閉包,針對(duì)所有的元素,只要滿足添加就可以輸出。
example(of: "filter") {
let bag = DisposeBag()
// 1. 創(chuàng)建一個(gè)序列
Observable.of(1, 2, 3, 4, 5, 6)
.filter{ $0 % 2 == 0} // 2. 過濾偶數(shù)
.subscribe(onNext: { // 3. 訂閱
print($0)
})
.disposed(by: bag)
// 輸出: 2 4 6
}
Transforming Operators
skip
特點(diǎn): 跳過指定數(shù)量的元素。

示例代碼:
/// 1. skip() : 跳過指定數(shù)量的元素
example(of: "skip") {
let bag = DisposeBag()
// 1. 序列
Observable.of("A", "B", "C", "D", "E", "F")
.skip(3) // 2. 跳過三個(gè)元素
.subscribe( onNext: { // 3. 訂閱
print($0)
})
.disposed(by: bag)
// 輸出: D E F
}
skipWhile

/// 2. skipWhile : 像 skip 一樣決定哪些元素被忽略。
/// skipWhile 只跳過元素,直到第一個(gè)元素被允許通過,然后所有剩余的元素都被允許通過。
/// 閉包 返回 true 對(duì)應(yīng)的元素將被忽略;返回 false 對(duì)應(yīng)的元素通過。
/// 與 filter 操作相反。
example(of: "skipWhile") {
let bag = DisposeBag()
Observable.of(2, 2, 3, 4, 4) // 1. 序列
.skipWhile { $0 % 2 == 0} // 2. 跳過 開始時(shí)的 偶數(shù)
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 輸出: 3 4 4
}
skipUntil

/// 以上都是靜態(tài)的條件過濾元素,如果想基于其他序列動(dòng)態(tài)過濾元素怎么辦?
/// 3. skipUntil : 它將保持跳過原序列所有元素,直到觸發(fā)序列發(fā)射 .next 事件,開始輸出后續(xù)元素。
example(of: "skipUntil") {
let bag = DisposeBag()
// 1. 一個(gè)源序列,一個(gè)觸發(fā)序列
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
// 2.
subject
.skipUntil(trigger) // 直到 trigger 序列有 .next 事件
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
subject.onNext("A")
subject.onNext("B") // 未輸出
trigger.onNext("X") // 觸發(fā)
subject.onNext("C")
// 輸出:C
}
Taking Operators
take

/// Taking 是與 Skipping 相反的操作。
/// 1. take: 獲取幾個(gè)元素
example(of: "take") {
let bag = DisposeBag()
Observable.of(4, 5, 6, 7, 8, 9)
.take(3) // 獲取三個(gè)元素
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 輸出: 4 5 6
}
takeWhile

/// 2. takeWhile: 與 skipWhile 類似,不同點(diǎn)是用 taking 代替 skipping
example(of: "takeWhile") {
let bag = DisposeBag()
Observable.of(2, 2, 4, 4, 6, 6)
.enumerated() // 1. 獲取元組包含 index 和 element
.takeWhile({ index, integer in // 2. 直到條件不成立停止
integer % 2 == 0 && index < 3
})
.map { $0.element } // 3. 獲取元素,生成只包含元素的序列
.subscribe(onNext: { // 4. 訂閱輸出
print($0)
})
.disposed(by: bag)
// 輸出: 2 2 4
}
takeUntil

/// 3. takeUntil: 與 skipUntil 類似
/// 持續(xù)獲取源序列中元素,直到觸發(fā)序列發(fā)送 .next 事件。
example(of: "takeUntil") {
let bag = DisposeBag()
// 1.
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
// 2.
subject
.takeUntil(trigger)
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 3.
subject.onNext("A")
subject.onNext("B")
trigger.onNext("1") // 觸發(fā)序列終止源序列
subject.onNext("C")
// 輸出:A B
// 思考:是不是可以通過 takeUntil 監(jiān)控 VC 的銷毀。
}
Distinct Operators
distinctUntilChanged

/// 1. distinctUntilChanged : 阻止下一個(gè)重復(fù)元素
/// 只阻止相鄰重復(fù)元素。
example(of: "distinctUntilChanged") {
let bag = DisposeBag()
Observable.of("A", "A", "B", "B", "A")
.distinctUntilChanged()
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 輸出:A B A
}
distinctUntilChanged(_:)
/// 2. distinctUntilChanged(_:) 自定義比較
example(of: "distinctUntilChanged(_:)") {
let bag = DisposeBag()
// 1
let formatter = NumberFormatter()
formatter.numberStyle = .spellOut // 朗讀形式,英文,例如:110 ==> ["one", "hundred", "ten"]
// 2. 序列
Observable<NSNumber>.of(10, 110, 20, 200, 210, 310)
// 3
.distinctUntilChanged { a, b in
guard let aWords = formatter.string(from: a)?.components(separatedBy: " "),
let bWords = formatter.string(from: b)?.components(separatedBy: " ")
else {return false}
print(aWords, bWords)
var containsMatch = false
for aWord in aWords where bWords.contains(aWord) {
containsMatch = true
break
}
return containsMatch
/*
第一次:["ten"] ["one", "hundred", "ten"] ==> true, 跳過 110
第二次:["ten"] ["twenty"] ==> false
第三次:["twenty"] ["two", "hundred"] ==> false
第四次:["two", "hundred"] ["two", "hundred", "ten"] ==> true,跳過 210
第五次:["two", "hundred"] ["three", "hundred", "ten"] ==> true, 跳過 310
*/
}
// 訂閱
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
}