RxSwift學(xué)習(xí)教程之基礎(chǔ)篇
前言
我們?cè)?iOS 開(kāi)發(fā)過(guò)程中,幾乎無(wú)時(shí)無(wú)刻都要面對(duì)異步事件的處理。例如,按鍵點(diǎn)擊、數(shù)據(jù)保存、、音頻后臺(tái)播放、交互動(dòng)畫展示。這些事件并不具備特定時(shí)序性,甚至它們可能同時(shí)發(fā)生。
雖然 Apple 提供了通知、代理、GCD、閉包等異步機(jī)制,但是這些機(jī)制缺乏一個(gè)統(tǒng)一的抽象表述。另外,這些機(jī)制在處理共享的可變數(shù)據(jù)或狀態(tài)時(shí)不夠清晰簡(jiǎn)練。當(dāng)然,這并不是說(shuō)編寫優(yōu)雅的異步代碼不現(xiàn)實(shí)。畢竟與其他平臺(tái)相比 iOS 的異步機(jī)制還是很強(qiáng)大的。
幸運(yùn)的是,我們能夠通過(guò) RxSwift 優(yōu)雅的處理異步代碼。
至于 RxSwift 的優(yōu)勢(shì)以及為什么要使用它,詳見(jiàn)文檔。這里就不廢話了。
RxSwift 簡(jiǎn)介
其實(shí)響應(yīng)式編程并不是一個(gè)什么新的概念,只不過(guò)是最近幾年受到了開(kāi)發(fā)者更多的關(guān)注。它最早由巨硬提出,主要的目的是為了應(yīng)對(duì)復(fù)雜的 UI 異步事件和應(yīng)用實(shí)時(shí)響應(yīng)。社區(qū)中也已經(jīng)有了各種語(yǔ)言版本的響應(yīng)式編程實(shí)現(xiàn),包括:RxJS、RxKotlin、Rx.NET、RxScala、RxSwift。這些類庫(kù)僅僅只是實(shí)現(xiàn)方式存在差異,所以開(kāi)發(fā)者在討論應(yīng)用邏輯時(shí)不會(huì)存在溝通障礙。
RxSwift 作為 Swift 語(yǔ)言的響應(yīng)式編程實(shí)現(xiàn),它在傳統(tǒng)的命令式編程和純函數(shù)式編程中找到了一個(gè)很好的平衡點(diǎn)。通過(guò)使用不可變代碼定義異步處理輸入,RxSwift 以一種確定可組合的形式對(duì)事件做出響應(yīng)。
總的來(lái)說(shuō),RxSwift 有三個(gè)主要構(gòu)成部分:Observable、Operator、Scheduler 。下面我們就來(lái)一一介紹。
Observable
Observable<T> 類可以說(shuō)是 RxSwift 整個(gè)框架的基石。它能異步的觸發(fā)一系列事件流并攜帶不可更改的狀態(tài)變量。簡(jiǎn)單來(lái)說(shuō)就是:它能讓某個(gè)類的實(shí)例在一段時(shí)間內(nèi)實(shí)現(xiàn)對(duì)另一個(gè)實(shí)例對(duì)象值的觀察。例如:觀察者可以捕獲對(duì)所有可觀察對(duì)象觸發(fā)的事件,從而實(shí)現(xiàn) UI 的實(shí)時(shí)更新或者是數(shù)據(jù)的實(shí)時(shí)處理。
其中 Observable<T> 類遵循了 ObservableType 協(xié)議。另外,Observable 對(duì)象所能觸發(fā)的事件只有以下三種:
- next 事件:該事件在觸發(fā)時(shí)會(huì)將可觀察對(duì)象的最新值傳遞給觀察者。
- completed 事件:該事件意味著可觀察對(duì)象的生命周期正常結(jié)束不會(huì)在繼續(xù)觸發(fā)事件。
- error 事件:該事件表明可觀察對(duì)象出現(xiàn)了錯(cuò)誤導(dǎo)致生命周期異常終止。
對(duì)于一個(gè)可觀察的整型變量來(lái)說(shuō),異步環(huán)境下它所觸發(fā)的事件可以在時(shí)間線上被描繪成這樣一個(gè)事件序列:

另外,我們可以對(duì)這三類事件進(jìn)行組合從而實(shí)現(xiàn)更為復(fù)雜的業(yè)務(wù)邏輯。與此同時(shí),我們還可以使用該機(jī)制輕松實(shí)現(xiàn)代碼解耦和多個(gè)對(duì)象間數(shù)據(jù)傳遞,無(wú)需編寫代理或者閉包代碼。

這里,我們還有一點(diǎn)值得注意。那就是可觀察序列其實(shí)有兩種類型。
有限觀察序列( Finite observable sequences )
該序列是指那些最后會(huì)以 completed 或者 error 事件終極生命周期的可觀察對(duì)象。最典型的例子就是,通過(guò) API 進(jìn)行網(wǎng)絡(luò)請(qǐng)求:
- 開(kāi)始數(shù)據(jù)請(qǐng)求并準(zhǔn)備進(jìn)行數(shù)據(jù)接收。
- 接收到服務(wù)端響應(yīng)開(kāi)始接收數(shù)據(jù)。
- 如果服務(wù)器或者網(wǎng)絡(luò)發(fā)生故障則關(guān)閉請(qǐng)求并觸發(fā)錯(cuò)誤處理。
- 如果一切正常則對(duì)請(qǐng)求數(shù)據(jù)進(jìn)行處理和分析。
下面是一個(gè)文件下載請(qǐng)求的 Rx 范式的代碼:
API.download(file: "http://www...")
.subscribe( onNext: { data in
append data to temporary file },
onError: { error in
display error to user },
onCompleted: {
use downloaded file })
這段代碼中 API.download (file:) 函數(shù)會(huì)創(chuàng)建一個(gè) Observable<Data> 實(shí)例對(duì)象,并且在整個(gè)數(shù)據(jù)接收過(guò)程中會(huì)不斷的觸發(fā) next 事件。然后,我們?cè)?next 事件中會(huì)將這些片段數(shù)據(jù)保存到臨時(shí)文件中。如果此過(guò)程出現(xiàn)錯(cuò)誤的話,我們會(huì)將錯(cuò)誤信息展示給用戶。如果一切順利我們會(huì)將臨時(shí)文件保存到設(shè)備中。最后在下載完成后,我們可以在 completed 進(jìn)行下一步的邏輯處理。
無(wú)限觀察序列( Infinite observable sequences )
與網(wǎng)絡(luò)任務(wù)不同的是,UI 以及交互事件是無(wú)限觀察序列。它們并不存在一個(gè)明確的生命周期終結(jié)點(diǎn)。例如,針對(duì)可能的設(shè)備方向旋轉(zhuǎn),我們需要實(shí)時(shí)進(jìn)行布局修改。而設(shè)備的方向旋轉(zhuǎn)本身是隨機(jī)發(fā)生的并且與應(yīng)用本身具有同樣的生命周期。因此 Rx 也需要一種機(jī)制支持這種無(wú)限觀察序列。
針對(duì)這種情況,在 RxSwift 中我們可以通過(guò)以下代碼來(lái)應(yīng)對(duì):
UIDevice.rx.orientation.subscribe(onNext: { current in
switch current {
case .landscape:
re-arrange UI for landscape
case .portrait:
re-arrange UI for portrait
}
})
操作符
ObservableType 以及 Observable 類的實(shí)現(xiàn)中都包含大量的異步處理方法,這些方法也被稱為操作符。由于這些操作符只是進(jìn)行異步輸入處理并產(chǎn)生對(duì)應(yīng)輸出,所以它并不會(huì)對(duì)應(yīng)用產(chǎn)生多余的副作用。另外,因?yàn)椴僮鞣g的高度解耦所以我們很容易對(duì)它進(jìn)行組合以期實(shí)現(xiàn)復(fù)雜的功能。
例如,對(duì)于上面的設(shè)備方向旋轉(zhuǎn),我們可以對(duì)所有的情況進(jìn)行過(guò)濾然后對(duì)部分值進(jìn)行進(jìn)一步處理。
UIDevice.rx.orientation
.filter { value in
return value != .landscape
}
.map { _ in
return "Portrait is the best!"
}
.subscribe( onNext: { string in
showAlert(text: string)
})
上面的代碼中,我們首先會(huì)將所有 .landscape 方向過(guò)濾掉不做任何處理。然后,我們?cè)賹⑹O碌?portrait 轉(zhuǎn)化為字符串 Portrait is the best! 。整個(gè)處理流程大致如下:

這種函數(shù)式的操作符讓我們可以靈活的組合出更強(qiáng)大的功能。
Scheduler
Schedulers 是一個(gè)與 GCD 相對(duì)應(yīng)的概念,只不過(guò)前者使用起來(lái)更為方便。RxSwift 中預(yù)定義的 Schedulers 足夠開(kāi)發(fā)者應(yīng)對(duì)絕大多數(shù)的編程場(chǎng)景。
例如,我們可以使用串型序列 SerialDispatchQueueScheduler 來(lái)處理 next 事件,通過(guò) ConcurrentDispatchQueueScheduler 運(yùn)行并行文件下載任務(wù),通過(guò) OperationQueueScheduler 運(yùn)行一個(gè) NSOperationQueue 操作隊(duì)列。甚至你可以在同一個(gè)觀察對(duì)象的不同任務(wù)中使用不同的 Schedulers 類型,如下圖:

我們將左側(cè)的任務(wù)用不同的顏色加以區(qū)分,然后在右側(cè)任務(wù)被拆分為不同的步驟并且放在不同 Schedulers 中。例如,network subscription 任務(wù)就被拆分為三個(gè)步驟并依次放入了 Custom NSOperation Scheduler 、Background Concurrent Scheduler、Main Thred Serial Scheduler 。
補(bǔ)充
值得注意的是, RxSwift 并沒(méi)有對(duì)客戶端的應(yīng)用架構(gòu)作出硬性規(guī)定。這意味著,我們可以在已有項(xiàng)目中引入 RxSwift 進(jìn)行響應(yīng)式編程實(shí)踐。當(dāng)然已有框架中必定存在一個(gè)最適合 RxSwift 的,而它就是 MVVM。因?yàn)樵?MVVM 中我們可以將 VM 中的部分屬性直接與 UI 進(jìn)行綁定。

另外,對(duì)于 iOS 編程來(lái)說(shuō)僅僅有 RxSwift 是遠(yuǎn)遠(yuǎn)不夠的。RxSwift 只是 Swift 語(yǔ)言的響應(yīng)式實(shí)現(xiàn),我們還需要一種 Cocoa 層面的實(shí)現(xiàn)。好在這里存在 RxCocoa 作為 UIKit 的響應(yīng)式補(bǔ)充。前面設(shè)備方向代碼 UIDevice.rx.orientation 就是 RxCocoa 的應(yīng)用 。
總結(jié)
作為系列開(kāi)篇,本文介紹了 RxSwift 的一些基本理念和構(gòu)成,更多相關(guān)的內(nèi)容將會(huì)在后面帶來(lái)。
好了,以上就是這篇文章的全部?jī)?nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,謝謝大家對(duì)腳本之家的支持。
相關(guān)文章
Swift使用transform 實(shí)現(xiàn)重復(fù)平移動(dòng)畫效果
這篇文章主要介紹了Swift使用transform 實(shí)現(xiàn)重復(fù)平移動(dòng)畫效果,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-07-07
swift如何利用系統(tǒng)庫(kù)將漢字轉(zhuǎn)換為拼音詳解
將漢字轉(zhuǎn)換為拼音更利于我們大家開(kāi)發(fā)搜索功能,所以這篇文章主要給大家介紹了關(guān)于swift如何利用系統(tǒng)庫(kù)將漢字轉(zhuǎn)換為拼音的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-10-10
swift實(shí)現(xiàn)自定義圓環(huán)進(jìn)度提示效果
這篇文章主要為大家詳細(xì)介紹了swift實(shí)現(xiàn)自定義圓環(huán)進(jìn)度提示效果,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2016-05-05
SwiftUI 中創(chuàng)建反彈動(dòng)畫的實(shí)現(xiàn)
這篇文章主要介紹了SwiftUI 中創(chuàng)建反彈動(dòng)畫的實(shí)現(xiàn),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-10-10
Swift 3.0基礎(chǔ)學(xué)習(xí)之閉包
Swift引進(jìn)了閉包的概念,這個(gè)與object-c的block類似,使用過(guò)block的話都知道有多方便,所以開(kāi)始學(xué)Swift,先要把閉包學(xué)會(huì),后面使用會(huì)很頻繁。下面這篇文章主要介紹了Swift 3.0基礎(chǔ)學(xué)習(xí)之閉包的相關(guān)資料,需要的朋友可以參考借鑒,下面來(lái)一起看看吧。2017-03-03
Swift4使用GCD實(shí)現(xiàn)計(jì)時(shí)器
這篇文章主要為大家詳細(xì)介紹了Swift4使用GCD實(shí)現(xiàn)計(jì)時(shí)器,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2020-03-03

