RxSwift 深入淺出(二)高階函數(shù)

RxSwift 這個(gè)框架看我就夠了,這一篇我重點(diǎn)介紹高階函數(shù),掌握好RxSwift的高階函數(shù),是你通往成功的捷徑蜡峰。搞RxSwift摔认,我是認(rèn)真的

RxSwift 寶圖鎮(zhèn)博,咔咔點(diǎn)贊~~~~

Rxswift
import Foundation

import RxSwift
import RxCocoa

class FilteringVC: UIViewController {
    
    let disposedB = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.orange
        
//        testFilter()
        testDistinctUntilChanged()
//        testSingle()
//        testElementAt()
//        testIgnoreElements()
//        testTake()
//        testTakeLast()
//        testSkip()
//        testSample()
//        testDebounce()
        
    }
    
    func testFilter(){
        //該操作符就是用來(lái)過(guò)濾掉某些不符合要求的事件。
        Observable.of(2, 30, 22, 5, 60, 3, 40 ,9)
            .filter {
                $0 > 10
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testDistinctUntilChanged(){
        //該操作符用于過(guò)濾掉連續(xù)重復(fù)的事件蚌卤。
        Observable.of(2, 2, 2, 5, 60, 3, 40 ,9)
            .distinctUntilChanged()
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testSingle(){
        Observable.of(2, 30, 22, 5, 60, 3, 40 ,9)
            .filter {
                $0 > 10
            }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testElementAt(){
        //        只發(fā)送你選定的那個(gè)元素
        Observable.of(1, 2, 3, 4)
            .elementAt(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testIgnoreElements(){
//        該操作符可以忽略掉所有的元素,只發(fā)出 error或completed 事件。
//        如果我們并不關(guān)心 Observable 的任何元素赎婚,只想知道 Observable 在什么時(shí)候終止,那就可以使用 ignoreElements 操作符樱溉。
        Observable.of(1, 2, 3, 4)
            .ignoreElements()
            .subscribe{
                print($0)
            }
            .disposed(by: disposedB)
    }
    
    func testTake(){
        //   該方法實(shí)現(xiàn)僅發(fā)送 Observable 序列中的前 n 個(gè)事件挣输,在滿足數(shù)量之后會(huì)自動(dòng) .completed。
        Observable.of(1, 2, 3, 4)
            .take(1)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testTakeLast(){
        //   該方法實(shí)現(xiàn)僅發(fā)送 Observable序列中的后 n 個(gè)事件福贞。
        Observable.of(1, 2, 3, 4)
            .takeLast(1)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    
    func testSkip(){
        //   跳過(guò)源 Observable 序列發(fā)出的前 n 個(gè)事件撩嚼。
        Observable.of(1, 2, 3, 4)
            .skip(2)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
    func testSample(){
        //  通過(guò) notifier 的事件 - 會(huì)觸發(fā)  source 的響應(yīng),而如果兩次 notifier 事件之間沒(méi)有源序列的事件挖帘,則不發(fā)送值完丽。
        let source = PublishSubject<Int>()
        let notifier = PublishSubject<String>()
        source.sample(notifier)
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
        source.onNext(1)
        //讓源序列接收接收消息
        notifier.onNext("A")
        source.onNext(2)
        //讓源序列接收接收消息
        notifier.onNext("B")
        notifier.onNext("C")
        source.onNext(3)
        source.onNext(4)
        //讓源序列接收接收消息
        notifier.onNext("D")
        source.onNext(5)
        //讓源序列接收接收消息
        notifier.onCompleted()
    
    }
    func testDebounce(){
//        debounce 操作符可以用來(lái)過(guò)濾掉高頻產(chǎn)生的元素,它只會(huì)發(fā)出這種元素:該元素產(chǎn)生后拇舀,一段時(shí)間內(nèi)沒(méi)有新元素產(chǎn)生逻族。
//        換句話說(shuō)就是,隊(duì)列中的元素如果和下一個(gè)元素的間隔小于了指定的時(shí)間間隔骄崩,那么這個(gè)元素將被過(guò)濾掉聘鳞。
//        debounce 常用在用戶輸入的時(shí)候,不需要每個(gè)字母敲進(jìn)去都發(fā)送一個(gè)事件要拂,而是稍等一下取最后一個(gè)事件抠璃。
//
        //定義好每個(gè)事件里的值以及發(fā)送的時(shí)間
        let times = [ [ "value": 1, "time": 0.1 ],
                      [ "value": 2, "time": 1.1 ],
                      [ "value": 3, "time": 1.2 ],
                      [ "value": 4, "time": 1.2 ],
                      [ "value": 5, "time": 1.4 ],
                      [ "value": 6, "time": 2.1 ] ]
            //生成對(duì)應(yīng)的 Observable 序列并訂閱
        Observable.from(times)
            .flatMap { item in
                return Observable.of(Int(item["value"]!))
                    .delaySubscription(Double(item["time"]!), scheduler: MainScheduler.instance)
            }
            .debounce(0.5, scheduler: MainScheduler.instance) //只發(fā)出與下一個(gè)間隔超過(guò)0.5秒的元素
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
    }
}

上面是經(jīng)常使用的高階函數(shù),其實(shí)和swift的高階函數(shù)是非常類(lèi)似的脱惰,下面再講幾個(gè)有意思的高階函數(shù)

class ViewController: UIViewController {

    let disposedB = DisposeBag()
    
    override func viewDidLoad() {
        super.viewDidLoad()

//        testBuffer()
//        testWindow()
//        testMap()
//        testFlatMap()
//        testConcatMap()
//        testGroupBy()
        
        self.present(FilteringVC(), animated: true, completion: nil)
    }
    
    func testGroupBy(){

//        groupBy 操作符將源 Observable 分解為多個(gè)子 Observable鸡典,然后將這些子 Observable 發(fā)送出來(lái)。
//        也就是說(shuō)該操作符會(huì)將元素通過(guò)某個(gè)鍵進(jìn)行分組枪芒,然后將分組后的元素序列以 Observable 的形態(tài)發(fā)送出來(lái)彻况。

        Observable<Int>.of(1,2,3,4,5,6,7,8,9)
            .groupBy(keySelector: { (element) -> String in
                return element % 2 == 0 ? "偶數(shù)" : "基數(shù)"
            })
            .subscribe { (event) in
                switch event{
                case .next(let group):
                    group.asObservable()
                        .subscribe({ (event) in
                        print("event==\(event): \n key = \(group.key)")
                    })
                        .disposed(by:self.disposedB)
                case .completed:
                    print("完成")
                case .error(let myError):
                    print(myError)
                }
                
        }
         .disposed(by:disposedB)
        
        
    }
    
    func testConcatMap(){
        
        //concatMap 與 flatMap 的唯一區(qū)別是:當(dāng)前一個(gè) Observable 元素發(fā)送完畢后,后一個(gè)Observable 才可以開(kāi)始發(fā)出元素舅踪∨Ω剩或者說(shuō)等待前一個(gè) Observable 產(chǎn)生完成事件后,才對(duì)后一個(gè) Observable 進(jìn)行訂閱抽碌。
        let subject1 = BehaviorSubject(value: "A")
        let subject2 = BehaviorSubject(value: "1")
        let variable = Variable(subject1) //這里裝進(jìn)去1
        variable.asObservable()
            .concatMap { $0 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
        
        subject1.onNext("B")
        variable.value = subject2 //裝進(jìn)去2
        subject2.onNext("2")
        subject1.onNext("C")
        
        /**
         A
         B
         C ==>發(fā)現(xiàn)沒(méi)有打印 1,2的數(shù)據(jù),說(shuō)明了subject1還沒(méi)有完成
         */
        subject1.onCompleted()
        /**
         A
         B
         C
         2 //為什么沒(méi)有打印1 因?yàn)樵趦?chǔ)存訂閱的時(shí)候,發(fā)現(xiàn)1沒(méi)有訂閱,結(jié)果被2替換了儲(chǔ)存,之后訂閱,就能打印了
         */
    }
    
    func testFlatMap(){
//        map 在做轉(zhuǎn)換的時(shí)候容易出現(xiàn)“升維”的情況悍赢。即轉(zhuǎn)變之后决瞳,從一個(gè)序列變成了一個(gè)序列的序列。
//        而 flatMap 操作符會(huì)對(duì)源 Observable 的每一個(gè)元素應(yīng)用一個(gè)轉(zhuǎn)換方法左权,將他們轉(zhuǎn)換成 Observables皮胡。 然后將這些 Observables 的元素合并之后再發(fā)送出來(lái)。即又將其 "拍扁"(降維)成一個(gè) Observable 序列赏迟。
//        這個(gè)操作符是非常有用的屡贺。比如當(dāng) Observable 的元素本生擁有其他的 Observable 時(shí),我們可以將所有子 Observables 的元素發(fā)送出來(lái)锌杀。
      
        let subject1 = BehaviorSubject(value: "A")
        let subject2 = BehaviorSubject(value: "1")
        let variable = Variable(subject1) //這里裝進(jìn)去1
        variable.asObservable()
            .flatMap { $0 }
            .subscribe(onNext: { print($0) })
            .disposed(by: disposedB)
        
        subject1.onNext("B")
        variable.value = subject2 //裝進(jìn)去2
        subject2.onNext("2")
        subject1.onNext("C")
        //這樣12都能打印
   
    }
    
    func testMap(){
    
        //該操作符通過(guò)傳入一個(gè)函數(shù)閉包把原來(lái)的 Observable 序列轉(zhuǎn)變?yōu)橐粋€(gè)新的 Observable 序列甩栈。
        let subject = PublishSubject<String>()
        subject.map { (str) -> String in
            return str+"hello"
            }
            .subscribe(onNext: { (event) in
                print(event)
            }, onError: nil, onCompleted: {
                print("完成了")
            }) {
                print("銷(xiāo)毀了")
            }
            .disposed(by: disposedB)
        
        subject.onNext("Cooci")
        
    }
    
    func testWindow(){
    
//        window 操作符和 buffer 十分相似。不過(guò) buffer 是周期性的將緩存的元素集合發(fā)送出來(lái)糕再,而 window 周期性的將元素集合以 Observable 的形態(tài)發(fā)送出來(lái)量没。
//        同時(shí) buffer要等到元素搜集完畢后,才會(huì)發(fā)出元素序列突想。而 window 可以實(shí)時(shí)發(fā)出元素序列殴蹄。
        
        let subject = PublishSubject<String>()
        subject.window(timeSpan: 2, count: 2, scheduler: MainScheduler.instance)
            .subscribe(onNext: { (event) in
                print(event)
            }, onError: nil, onCompleted: {
                print("完成了")
            }) {
                print("銷(xiāo)毀了")
            }
            .disposed(by: disposedB)
        
        subject.onNext("111")
        subject.onNext("222")
        subject.onNext("333")
        
        subject.onNext("aaa")
        subject.onNext("bbb")
        subject.onNext("ccc")
        
    }
        
        
    
    func testBuffer(){
        //buffer 方法作用是緩沖組合,第一個(gè)參數(shù)是緩沖時(shí)間猾担,第二個(gè)參數(shù)是緩沖個(gè)數(shù)袭灯,第三個(gè)參數(shù)是線程。
        //該方法簡(jiǎn)單來(lái)說(shuō)就是緩存 Observable 中發(fā)出的新元素垒探,當(dāng)元素達(dá)到某個(gè)數(shù)量妓蛮,或者經(jīng)過(guò)了特定的時(shí)間,它就會(huì)將這個(gè)元素集合發(fā)送出來(lái)圾叼。
        
        let subject = PublishSubject<String>()
        subject.buffer(timeSpan: 2, count: 2, scheduler: MainScheduler.instance)
            .subscribe(onNext: { (event) in
                print(event)
            }, onError: nil, onCompleted: {
                print("完成了")
            }) {
                print("銷(xiāo)毀了")
        }
        .disposed(by: disposedB)
        subject.onNext("111")
        subject.onNext("222")
        subject.onNext("333")

        subject.onNext("aaa")
        subject.onNext("bbb")
        subject.onNext("ccc")
        
        //這里每?jī)擅氪蛴∫粋€(gè)事件
        //["111", "222"]
//        ["333", "aaa"]
//        ["bbb", "ccc"]
//        [] 當(dāng)所有事件完畢,不會(huì)有儲(chǔ)存事件,就會(huì)打印空
    }
    
}

感謝 @蘑菇De大灰狼 點(diǎn)出博客存在的紕漏蛤克,同時(shí)歡迎大家點(diǎn)出,謝謝

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末夷蚊,一起剝皮案震驚了整個(gè)濱河市构挤,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌惕鼓,老刑警劉巖筋现,帶你破解...
    沈念sama閱讀 217,084評(píng)論 6 503
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異箱歧,居然都是意外死亡矾飞,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,623評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門(mén)呀邢,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)洒沦,“玉大人,你說(shuō)我怎么就攤上這事价淌∩暄郏” “怎么了瞒津?”我有些...
    開(kāi)封第一講書(shū)人閱讀 163,450評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)括尸。 經(jīng)常有香客問(wèn)我巷蚪,道長(zhǎng),這世上最難降的妖魔是什么濒翻? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 58,322評(píng)論 1 293
  • 正文 為了忘掉前任屁柏,我火速辦了婚禮,結(jié)果婚禮上肴焊,老公的妹妹穿的比我還像新娘前联。我一直安慰自己功戚,他們只是感情好娶眷,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,370評(píng)論 6 390
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著啸臀,像睡著了一般届宠。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上乘粒,一...
    開(kāi)封第一講書(shū)人閱讀 51,274評(píng)論 1 300
  • 那天豌注,我揣著相機(jī)與錄音,去河邊找鬼灯萍。 笑死轧铁,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的旦棉。 我是一名探鬼主播齿风,決...
    沈念sama閱讀 40,126評(píng)論 3 418
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼绑洛!你這毒婦竟也來(lái)了救斑?” 一聲冷哼從身側(cè)響起,我...
    開(kāi)封第一講書(shū)人閱讀 38,980評(píng)論 0 275
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤真屯,失蹤者是張志新(化名)和其女友劉穎脸候,沒(méi)想到半個(gè)月后,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體绑蔫,經(jīng)...
    沈念sama閱讀 45,414評(píng)論 1 313
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡运沦,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,599評(píng)論 3 334
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了配深。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片携添。...
    茶點(diǎn)故事閱讀 39,773評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖凉馆,靈堂內(nèi)的尸體忽然破棺而出薪寓,到底是詐尸還是另有隱情亡资,我是刑警寧澤,帶...
    沈念sama閱讀 35,470評(píng)論 5 344
  • 正文 年R本政府宣布向叉,位于F島的核電站锥腻,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏母谎。R本人自食惡果不足惜瘦黑,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,080評(píng)論 3 327
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望奇唤。 院中可真熱鬧幸斥,春花似錦、人聲如沸咬扇。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 31,713評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)懈贺。三九已至经窖,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間梭灿,已是汗流浹背画侣。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 32,852評(píng)論 1 269
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留堡妒,地道東北人配乱。 一個(gè)月前我還...
    沈念sama閱讀 47,865評(píng)論 2 370
  • 正文 我出身青樓,卻偏偏與公主長(zhǎng)得像皮迟,于是被迫代替她去往敵國(guó)和親搬泥。 傳聞我的和親對(duì)象是個(gè)殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,689評(píng)論 2 354

推薦閱讀更多精彩內(nèi)容