前言
很久一段時間沒寫博客了,一方面是自己各種事情折騰,二是新項目開始用Swift了,邊學邊做忙死了,現(xiàn)在終于快忙完了。由于接下來項目要使用RxSwift,所以研究一下RxSwift。
RxSwift概要
RxSwift是Swift函數(shù)響應式編程的一個開源庫,由Github的ReactiveX組織開發(fā),維護。目前在GitHub上有10000+star。
RxSwift的目的是讓讓數(shù)據(jù)/事件流和異步任務能夠更方便的序列化處理,能夠使用Swift進行響應式編程。
RxSwift中的基本概念
Observable
在ReactiveX中一個觀察者(Observer)訂閱一個被觀察的對象。這個觀察者對Observable發(fā)出的無論是單個對象或者是一串對象作出反饋。這種模式有利于并發(fā)操作因為它不需要阻塞線程,當?shù)却粋€Observable發(fā)送對象的過程中,它建立一種像哨兵一樣的機制,我們稱之為觀察者,他會一直關注那個Observable然后做出適當?shù)姆磻T赗eactiveX對Observable的說明中,有這么一張圖:

在最上面的一排,就是一個Observable。從左到右,表示時間由遠到進的流動過程。上面的每一個形狀,就表示在某個時間點發(fā)生的事件,而最右邊的豎線則表示事件成功結束。
Operators
在RxSwift中,操作符operator也是一個很重要的概念,關于它的詳細介紹在ReactiveX官網(wǎng)可以看到。常用操作符分為兩大類,一類用于創(chuàng)建Observable;這些不同的方法可以針對不同的事件流生成Observable。另一類是接受Observable作為參數(shù),并返回意義新的Observable。
創(chuàng)建一個事件隊列
創(chuàng)建一個簡單的事件隊列很簡單,代碼如下:
_ = Observable.of(1,2,3,4,5,6,7,8,9)
_ = Observable.from([1,2,3,4,5,6,7,8,9])
上面這里我們就用了兩個operator來創(chuàng)建Observable:
-
of: 用固定數(shù)量的元素生成一個Observable; -
from: 用一個Sequence類型的對象創(chuàng)建一個Observable;
這兩個operator返回的結果是一樣的,都是一個包含1-9的Observable。
處理事件序列
在開發(fā)中,我們有時候因為各種需求需要對事件序列進行處理加工。例如我要把上面的事件序列變成一個字符串序列,用map操作符就可以做到。
_ = Observable.of(1,2,3,4,5,6,7,8,9).map({String($0)})
map是一個可以對Observable中的元素變形的operator,它返回一個新的Observable對象。
我們還可以篩選出符合條件的事件序列
_ = Observable.of(1,2,3,4,5,6,7,8,9).filter({$0 % 2 == 0})
上面filter篩選出一個只含有偶數(shù)的時間序列
看到filter和map感覺和集合中的filter和map方法非常類似,但它們執(zhí)行的邏輯卻截然不同。調用集合類型中的filter和map方法,表達的是同步執(zhí)行的概念,在調用方法的同事,結合就被立即加工處理了。但是我們創(chuàng)建的bservable,表達的是異步操作。Observable中的每一個元素,都可以理解為一個異步發(fā)生的時間。因此,當我們隊Observable調用filter和map方法時,只表示我們要對事件序列中的元素進行處理的邏輯,并不會立即對Observable中的元素進行處理。下面這個例子可以驗證:
_ = Observable.of(1,2,3,4,5,6,7,8,9)
.filter({
if $0 % 2 == 0 {
print($0)
return true
}
return false
})
執(zhí)行這段代碼,在控制臺上并沒有打印任何消息。也就是說,我們沒有實際執(zhí)行任何的篩選邏輯。
訂閱事件
上面的刷選什么時候會被執(zhí)行呢?那就是有人訂閱這個事件的時候。
let numberObservable = Observable.of(1,2,3,4,5,6,7,8,9)
.filter({
if $0 % 2 == 0 {
print($0)
return true
}
return false
})
numberObservable.subscribe { (event) in
print("event: \(event)")
}
上面這段代碼的執(zhí)行結果如下:
2
event: next(2)
4
event: next(4)
6
event: next(6)
8
event: next(8)
event: completed
這說明當我們訂閱了這個事件序列,我們就能夠關注到篩選的過程和結果了。
subscribe也是一個operator
在上面的例子中,我們可以看到最后有一個event: completed,這就表示Observable事件流成功結束了。
實際上,subscribe也是一個operator,用于把事件的訂閱者(Observer)和事件的產生者(Observable)關聯(lián)起來。而Observable和Observer之間,有著以下的約定:
- 當Observable正常發(fā)送事件時,會調用Observer提供的onNext方法,這個過程給你習慣上叫做emissions;
- 當Observable成功結束時,回到用Observer提供的onCompleted方法;因此,在最后一次調用onNext之后,就會調用onCompleted;
- 當Observable發(fā)生錯誤時,就會調用Observer提供的onError方法,并且,一旦發(fā)生錯誤,就不會再繼續(xù)發(fā)送其他時間了。對于調用onComplete和onNext的過程,習慣上叫做notifications;
在RxSwift里,還有一個約定,叫做onDisposed,指的是Observable使用的資源被回收的時候,會調用Observer提供的onDisposed方法。
Observable dispose
一般情況下,Observable分為兩種:
- 在有限的時間內會自動結束(Completed/Error),比如一個網(wǎng)絡請求當做一個序列,當網(wǎng)絡請求完成的時候,Observable自動結束,資源會被釋放
- 信號不會自己結束,最簡單的就是一個Timer,每隔一段時間就會發(fā)送一個新的信號過來,這時候就需要手動監(jiān)聽來釋放相應的資源。
手動監(jiān)聽釋放也分為兩種方法,分別是顯式釋放以及隱式釋放:
- 顯式釋放 直接調用釋放方法進行資源的釋放,如下面的實例
public func delay(_ delay: Double,
closure: @escaping (Void) -> Void) {
DispatchQueue.main.asyncAfter(
deadline: .now() + delay) {
closure()
}
}
let disposable =
Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.subscribe(
onNext: { print("Subscribed: \($0)") },
onDisposed: { print("The queue was disposed.") })
delay(3) {
disposable.dispose()
}
執(zhí)行效果如下:
Subscribed: 0
Subscribed: 1
Subscribed: 2
The queue was disposed.
上面代碼創(chuàng)建一個輔助函數(shù)delay(),然后在delay()之后直接調用dispose()方法,這是顯式釋放
- 隱式釋放 通過DisposeBag來進行,它類似于Objective-C中ARC的自動釋放池機制,當我們創(chuàng)建了某個實例后,會被添加到所在線程的自動釋放池中,而自動釋放池會在一個RunLoop周期后進行池子的釋放與重建;DisposeBag對于Rxswift就像自動釋放池一樣,我們把資源天機到DisposeBag中,讓資源隨著DIsposeBag一起釋放。如下實例:
var bag = DisposeBag()
Observable<Int>.interval(1, scheduler: MainScheduler.instance)
.subscribe(
onNext: { print("Subscribed: \($0)") },
onDisposed: { print("The queue was disposed.") })
.disposed(by: bag)
delay(3) {
bag = DisposeBag()
}
這個執(zhí)行效果和上面的是一樣的,這就是隱式釋放。
小結
RxSwift之路還很長,需要不斷學習,不斷積累。