iOS開發(fā)進(jìn)階 - RxSwift :Filter相關(guān)操作

前言

萬丈高樓平地起,前面兩篇地基已經(jīng)建好,現(xiàn)在開始第一層。
示例代碼請(qǐng)移步Github
RxSwift 4.4

從本篇開始接下來幾篇文章會(huì)詳細(xì)學(xué)習(xí) RxSwiftOperators,作為 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):ignoreElementelementAt 過濾序列元素。有時(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)
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容