前言
萬丈高樓平地起国葬,前面兩篇地基已經(jīng)建好宴树,現(xiàn)在開始第一層国章。
示例代碼請移步Github
RxSwift 4.4
從本篇開始接下來幾篇文章會詳細學習 RxSwift
中 Operators
愿阐,作為 Rx
編程的基石才写,可以使用它來轉(zhuǎn)換竹挡,處理和響應事件镀娶。
Operators
分為四個部分:
-
Filtering Operators
:過濾 -
Transforming Operators
: 轉(zhuǎn)換 -
Combing Operators
: 組合 -
Time-Based Operators
: 基于時間操作
接下來學習過濾相關的操作。
Filtering Operators
過濾操作分為四類:
分類 | 主要方法 | 說明 |
---|---|---|
Ignoring Operators |
ignoreElements elementAt filter
|
用于忽略一些元素 |
Skipping Operators |
skip skipWhile skipUntil
|
|
Taking Operators |
take takeWhile takeUntil
|
|
Distinct Operators |
distinctUntilChange distinctUntilChanged(_:)
|
從整體上了解要學習的內(nèi)容揪罕,接下來詳細分析各個操作作用梯码,特點及區(qū)別聯(lián)系。
Ignoring Operators
ignoreElements
特點:忽略所有的 .next
事件元素好啰,允許終止事件通過轩娶。如:.completed
和 .error
。是不是應該想起來什么框往?ignoreElements
實際上返回一個 Completable
鳄抒。
①:表示源序列,可以被訂閱
②:表示操作及參數(shù)
③:訂閱
實例代碼:
/// 1. ignoreElements : 忽略所有的 .next 事件元素搅窿,允許停止事件通過嘁酿,如 .completed 和 .error.
/// 也許會發(fā)現(xiàn):ignoreElements 實際上返回一個 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
特點: 獲取指定位置的元素。只要獲取到指定位置的元素男应,訂閱就終止闹司。
示例代碼:
/// 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
特點:ignoreElement
和 elementAt
過濾序列元素。有時不針對全部或單個元素操作耐朴。filter
提供了一個閉包借卧,針對所有的元素,只要滿足添加就可以輸出筛峭。
示例代碼:
/// 3. ignoreElement 和 elementAt 過濾序列元素铐刘。有時不針對全部或單個元素操作。
/// filter 提供了一個閉包影晓,針對所有的元素镰吵,只要滿足添加就可以輸出檩禾。
example(of: "filter") {
let bag = DisposeBag()
// 1. 創(chuàng)建一個序列
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
特點: 跳過指定數(shù)量的元素。
示例代碼:
/// 1. skip() : 跳過指定數(shù)量的元素
example(of: "skip") {
let bag = DisposeBag()
// 1. 序列
Observable.of("A", "B", "C", "D", "E", "F")
.skip(3) // 2. 跳過三個元素
.subscribe( onNext: { // 3. 訂閱
print($0)
})
.disposed(by: bag)
// 輸出: D E F
}
skipWhile
/// 2. skipWhile : 像 skip 一樣決定哪些元素被忽略疤祭。
/// skipWhile 只跳過元素盼产,直到第一個元素被允許通過,然后所有剩余的元素都被允許通過勺馆。
/// 閉包 返回 true 對應的元素將被忽略戏售;返回 false 對應的元素通過。
/// 與 filter 操作相反草穆。
example(of: "skipWhile") {
let bag = DisposeBag()
Observable.of(2, 2, 3, 4, 4) // 1. 序列
.skipWhile { $0 % 2 == 0} // 2. 跳過 開始時的 偶數(shù)
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 輸出: 3 4 4
}
skipUntil
/// 以上都是靜態(tài)的條件過濾元素灌灾,如果想基于其他序列動態(tài)過濾元素怎么辦?
/// 3. skipUntil : 它將保持跳過原序列所有元素悲柱,直到觸發(fā)序列發(fā)射 .next 事件紧卒,開始輸出后續(xù)元素。
example(of: "skipUntil") {
let bag = DisposeBag()
// 1. 一個源序列诗祸,一個觸發(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: 獲取幾個元素
example(of: "take") {
let bag = DisposeBag()
Observable.of(4, 5, 6, 7, 8, 9)
.take(3) // 獲取三個元素
.subscribe(onNext: {
print($0)
})
.disposed(by: bag)
// 輸出: 4 5 6
}
takeWhile
/// 2. takeWhile: 與 skipWhile 類似轴总,不同點是用 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 : 阻止下一個重復元素
/// 只阻止相鄰重復元素。
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)
}