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

另外,我們可以對這三類事件進行組合從而實現更為復雜的業務邏輯。與此同時,我們還可以使用該機制輕松實現代碼解耦和多個對象間數據傳遞,無需編寫代理或者閉包代碼。

這裏,我們還有一點值得註意。那就是可觀察序列其實有兩種類型。
有限觀察序列( Finite observable sequences )
該序列是指那些最後會以 completed 或者 error 事件終極生命周期的可觀察對象。最典型的例子就是,通過 API 進行網絡請求:
- 開始數據請求並準備進行數據接收。 接收到服務端響應開始接收數據。 如果服務器或者網絡發生故障則關閉請求並觸發錯誤處理。 如果一切正常則對請求數據進行處理和分析。
下面是一個文件下載請求的 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:) 函數會創建一個 Observable<Data> 實例對象,並且在整個數據接收過程中會不斷的觸發 next 事件。然後,我們在 next 事件中會將這些片段數據保存到臨時文件中。如果此過程出現錯誤的話,我們會將錯誤信息展示給用戶。如果一切順利我們會將臨時文件保存到設備中。最後在下載完成後,我們可以在 completed 進行下一步的邏輯處理。
無限觀察序列( Infinite observable sequences )
與網絡任務不同的是,UI 以及交互事件是無限觀察序列。它們並不存在一個明確的生命周期終結點。例如,針對可能的設備方向旋轉,我們需要實時進行布局修改。而設備的方向旋轉本身是隨機發生的並且與應用本身具有同樣的生命周期。因此 Rx 也需要一種機制支持這種無限觀察序列。
針對這種情況,在 RxSwift 中我們可以通過以下代碼來應對:
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 類的實現中都包含大量的異步處理方法,這些方法也被稱為操作符。由於這些操作符只是進行異步輸入處理並產生對應輸出,所以它並不會對應用產生多余的副作用。另外,因為操作符之間的高度解耦所以我們很容易對它進行組合以期實現復雜的功能。
例如,對於上面的設備方向旋轉,我們可以對所有的情況進行過濾然後對部分值進行進一步處理。
UIDevice.rx.orientation
.filter { value in
return value != .landscape
}
.map { _ in
return "Portrait is the best!"
}
.subscribe( onNext: { string in
showAlert(text: string)
})
上面的代碼中,我們首先會將所有 .landscape 方向過濾掉不做任何處理。然後,我們再將剩下的 portrait 轉化為字符串 Portrait is the best! 。整個處理流程大致如下:

這種函數式的操作符讓我們可以靈活的組合出更強大的功能。
Scheduler
Schedulers 是一個與 GCD 相對應的概念,只不過前者使用起來更為方便。RxSwift 中預定義的 Schedulers 足夠開發者應對絕大多數的編程場景。
例如,我們可以使用串型序列 SerialDispatchQueueScheduler 來處理 next 事件,通過 ConcurrentDispatchQueueScheduler 運行並行文件下載任務,通過 OperationQueueScheduler 運行一個 NSOperationQueue 操作隊列。甚至你可以在同一個觀察對象的不同任務中使用不同的 Schedulers 類型,如下圖:

我們將左側的任務用不同的顏色加以區分,然後在右側任務被拆分為不同的步驟並且放在不同 Schedulers 中。例如,Network subscription 任務就被拆分為三個步驟並依次放入了 Custom NSOperation Scheduler 、Background Concurrent Scheduler、Main Thred Serial Scheduler 。
補充
值得註意的是, RxSwift 並沒有對客戶端的應用架構作出硬性規定。這意味著,我們可以在已有項目中引入 RxSwift 進行響應式編程實踐。當然已有框架中必定存在一個最適合 RxSwift 的,而它就是 MVVM。因為在 MVVM 中我們可以將 VM 中的部分屬性直接與 UI 進行綁定。

另外,對於 iOS 編程來說僅僅有 RxSwift 是遠遠不夠的。RxSwift 只是 Swift 語言的響應式實現,我們還需要一種 Cocoa 層面的實現。好在這裏存在 RxCocoa 作為 UIKit 的響應式補充。前面設備方向代碼 UIDevice.rx.orientation 就是 RxCocoa 的應用 。
總結
作為系列開篇,本文介紹了 RxSwift 的一些基本理念和構成,更多相關的內容將會在後面帶來。
好了,以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作能帶來一定的幫助,如果有疑問大家可以留言交流,謝謝大家對電腦玩物的支持。
http://www.itread01.com/articles/1506448445.html
RxSwift學習教程之基礎篇的更多相关文章
- 邁向IT專家成功之路的三十則鐵律 鐵律八:IT人學習之道-基礎功
修練過中國武術的人都知道,任何一種拳法的學習最重要的就是基礎功,而基礎功又可分為內在與外在的修練,內在的修練強調在平心.靜氣.不爭的調息.至於外在這首重在站樁.鬆沉.不疾不徐的應對能力.有了深厚基礎的 ...
- Selenium自動化測試(Python+VS2013)-基礎篇-環境安裝
Python+VS2013環境安裝 http://www.cnblogs.com/aehyok/p/3986168.html PTVS: http://microsoft.github.io/PTVS ...
- GO語言基礎教程:序章
首先自我介紹一下我自己,我是一個coder,目前主要從事B/S程序開發工作,懂點PHP;ASP;JSP;JS;VB;C;DELPHI;JAVA,另外知道幾個數據庫,除此之外別無所長,那麼我為何會選擇學 ...
- 基於tiny4412的Linux內核移植--- 中斷和GPIO學習(3)
作者 彭東林 pengdonglin137@163.com 平臺 tiny4412 ADK Linux-4.4.4 u-boot使用的U-Boot 2010.12,是友善自帶的,爲支持設備樹和uIma ...
- 無心插柳的Linux學習者代言人——蔡德明
誰是「蔡德明」恐怕沒有多少人知道,不過提到「鳥哥」這個稱號,在臺灣的Linux社群幾乎是無人不知無人不曉,蔡德明正是鳥哥的本名.鳥哥究竟多有名? 如果你是有意學習Linux的初學者,卻不知如何下手,1 ...
- Java學習筆記(基本語法)
本文件是以學習筆記的概念為基礎,用於自我的複習紀錄,不過也開放各位的概念指證.畢竟學習過程中難免會出現觀念錯誤的問題.也感謝各位的觀念指證. 安裝JDK 在Oracle網站中找自己系統的JDK下載位置 ...
- Python 基礎 - if else流程判斷
hmm~前面講了那麼多,終於可以稍稍的正式進入另一個階段,沒錯,要開始寫判斷式了 這次先從最簡單的判斷式開始,if else 開始- Go 首先,之前有寫有一個簡單的互動式 用戶輸入 的代碼,忘記了嗎 ...
- 學習 DT device tree 以 ST 的開發板 STM32F429i-disc1 為例
目標 因為對 device tree 不是很熟悉, 所以就將 device tree, 設為學習目標. 啟動 注意, 這篇隨筆的解說都放在最下面,會標 Explanation_XX,只要搜尋 Expl ...
- 機器學習基石(Machine Learning Foundations) 机器学习基石 课后习题链接汇总
大家好,我是Mac Jiang,非常高兴您能在百忙之中阅读我的博客!这个专题我主要讲的是Coursera-台湾大学-機器學習基石(Machine Learning Foundations)的课后习题解 ...
随机推荐
- [luogu1129 ZJOI2007] 矩阵游戏 (二分图最大匹配)
传送门 Description Input Output Sample Input 2 2 0 0 0 1 3 0 0 1 0 1 0 1 0 0 Sample Output No Yes HINT ...
- 以豌豆荚为例,用 Scrapy 爬取分类多级页面
本文转载自以下网站:以豌豆荚为例,用 Scrapy 爬取分类多级页面 https://www.makcyun.top/web_scraping_withpython17.html 需要学习的地方: 1 ...
- Linux之浅谈VIM常见用法及原理图
本次归纳以强大的VIM文本处理工具常见用法去展开论述. 文本编辑种类: 行编辑器:sed 全屏编辑器:nano,vi vim - Vi改进 其他编辑器: ...
- 30.es增删改内部分发原理
当客户端发送一次请求时,大致会经过以下几个步骤 (1)客户端发送一个请求过去,es的一个node接收到这个请求(随机的),这个node就被es内部分配成coordinating node(协调 ...
- 学习EXTJS6(4)基本功能-信息提示框组件
1.使用组件,主要配置表现形式有二种(是否可以说参数) 用逗号分隔的传统参数列表方式: <script type="text/javascript"> Ext.onRe ...
- 通过UrlRewriter配置MVC4伪静态
有些项目须要设置静态.这样能够被站点收录了,提高站点的排名.内容. 假设地址后面有www.a.com/xx.html?id=1是不行,还是不能达到一些需求.怎么才干实现www.a.com/1/xx.h ...
- How to fix yum errors on CentOS, RHEL or Fedora
Yum is a package management tool for installing, updating and removing rpm packages on RedHat-based ...
- Java设计模式之从[星际争霸的兵种升级]分析观察者(Observer)模式
观察者模式定义对象的一种一对多的依赖关系.当一个对象的状态发生改变时.全部依赖于它的对象都会得到通知并被自己主动更新. 一个简单的样例是.在星际争霸的虫族中有一个0基础单位叫做跳狗(Zergling) ...
- Activiti的简单入门样例(经典的请假样例)
经典的请假样例: 流程例如以下,首先须要部门经理审批.假设请假天数大于2天,则须要总经理审批,否则HR审批就可以 一:创建maven项目,项目结构例如以下: watermark/2/text/aHR0 ...
- Linux - 如何关闭防火墙
关闭防火墙,就可以外部访问了.不受端口限制.生产环境,最好开启防火墙,开启部分端口. 1.永久有效 开启: chkconfig iptables on 关闭: chkconfig iptables o ...