RxSwift 是什么
RxSwift 是Rx框架的 Swift 實(shí)現(xiàn).
關(guān)于 Rx 框架引用一段介紹https://mcxiaoke.gitbooks.io/rxdocs/content/Intro.html
ReactiveX是Reactive Extensions的縮寫(xiě),一般簡(jiǎn)寫(xiě)為Rx,最初是LINQ的一個(gè)擴(kuò)展店雅,由微軟的架構(gòu)師Erik Meijer領(lǐng)導(dǎo)的團(tuán)隊(duì)開(kāi)發(fā)震贵,在2012年11月開(kāi)源铝条,Rx是一個(gè)編程模型凿叠,目標(biāo)是提供一致的編程接口虚汛,幫助開(kāi)發(fā)者更方便的處理異步數(shù)據(jù)流,Rx庫(kù)支持.NET刺桃、JavaScript和C++,Rx近幾年越來(lái)越流行了吸祟,現(xiàn)在已經(jīng)支持幾乎全部的流行編程語(yǔ)言了瑟慈,Rx的大部分語(yǔ)言庫(kù)由ReactiveX這個(gè)組織負(fù)責(zé)維護(hù)桃移,比較流行的有RxJava/RxJS/Rx.NET,社區(qū)網(wǎng)站是 reactivex.io葛碧。
框架的主要目的是為了處理異步數(shù)據(jù)流. 例如, 異步網(wǎng)絡(luò)請(qǐng)求, 事件響應(yīng)等
RxSwift 的意義及為何要使用這個(gè)框架
簡(jiǎn)單來(lái)說(shuō), 你可以更方便高效的寫(xiě)代碼. 例如官方這個(gè)炫酷的 demo, 你也可以很方便的寫(xiě)出來(lái)
而且合理使用各種合并, map, flatmap 等, 你幾乎可以完成所有的事情.
入門(mén)
首先我們要導(dǎo)入 RxSwift. 只需要在 Pod 文件中加入這一行
pod 'RxSwift', '~> 3.0'
成功導(dǎo)入之后,
我們來(lái)看一個(gè)最基本的 Hello, word
class SomeViewController: UIViewController {
...
let disposeBag = DisposeBag()
....
override func viewDidLoad() {
Observable.just("Hello, world").subscribe(onNext: { (str) in
print(str)
}).disposed(by: disposeBag)
}
...
這個(gè)示例會(huì)輸出Hello, world
不過(guò)你現(xiàn)在覺(jué)得一頭霧水, 這是什么? Observable
是什么東西?
基礎(chǔ)概念
RxSwift 中大量使用到觀察者模式. 這個(gè)模式在 iOS 中應(yīng)用最廣泛的就是通知了.
Observable
Observable
是一個(gè)可觀察的對(duì)象, 類似于 NotificationCenter
我們使用 just
這個(gè)工廠方法, 創(chuàng)建了一個(gè)可觀察者對(duì)象, 并在其中放了一個(gè)事件, 這個(gè)事件內(nèi)容就是這個(gè)"Hello, world" 字符串, 并隨即事件鏈結(jié)束. 相當(dāng)于使用 NotificationCenter.default.post(xxx)
, 不過(guò)這里略有不同的是, 通知會(huì)立即發(fā)送, 而可觀察對(duì)象通常會(huì)在有訂閱者訂閱的時(shí)候才會(huì)創(chuàng)建事件并發(fā)送.
subscribe
subscribe(onNext:)
則是訂閱, 相當(dāng)于 NotificationCenter.default.addObserver
. Observable 中有三種事件, 分別是完成completed
, 錯(cuò)誤 error(Error)
, 下一個(gè)"next(Element)". 這里的 next 事件看似難以理解, 其實(shí)只是說(shuō)發(fā)生了某一個(gè)事件而已. 關(guān)于事件, 后面我們?cè)偌?xì)說(shuō).
回到之前的代碼, subscribe(onNext:)
則表示我們要訂閱一個(gè) next 事件. 之前提到, just
函數(shù)會(huì)在發(fā)送一次事件之后立即結(jié)束, 這里我們也可以通過(guò)訂閱來(lái)看到, 修改代碼為如下代碼, 以打印所有事件
Observable.just("Hello, world").subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
可以看到, 事件的順序是next(Hello, world) => completed
disposeable
這個(gè)用于清理空間, 以及完成某些收尾工作.
在subscribe
后, 會(huì)返回一個(gè)disposeable
對(duì)象, 可以將這個(gè)對(duì)象放入某個(gè) disposeBag
, 當(dāng)這個(gè)disposeBag
對(duì)象被釋放的時(shí)候, 會(huì)同時(shí)銷毀所有與之關(guān)聯(lián)的disposeable對(duì)象.
事件
RxSwift 中最重要的就是事件, 核心就是若干消息的消息鏈處理.
除了我們之前用到的just
之外, 還有一些其他方法可以產(chǎn)生多次事件, 例如of
Observable.of("Hello", "world").subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
這段代碼的輸出結(jié)果為
next(Hello)
next(world)
completed
RxSwift 中只有兩種事件鏈, 一種是無(wú)盡的的, 也就是沒(méi)有complete 事件. 一種則是有限長(zhǎng)度的.
-1-2-3-4-|
這個(gè)是有限長(zhǎng)度的事件鏈, 1, 2, 3, 4 是事件, |
是結(jié)束標(biāo)記
-1-2-3-4-
這個(gè)則是無(wú)限的長(zhǎng)度的事件鏈, 因?yàn)椴](méi)有結(jié)束符
-1-2-3-4-×
則表示發(fā)生了錯(cuò)誤, ×
表示錯(cuò)誤
需要注意的是, 只要了錯(cuò)誤或者發(fā)送了結(jié)束事件, 那么后續(xù)所有的事件都會(huì)被忽略
創(chuàng)建自定義事件鏈
如果系統(tǒng)定義的事件鏈不能滿足需要, 你需要自定義, 你可以 create 來(lái)辦到這一點(diǎn)
例如, 我們來(lái)寫(xiě)一個(gè)跟 just 類似的, 只發(fā)送一個(gè)事件后就立即結(jié)束事件鏈
Observable<String>.create { (observer) -> Disposable in
observer.onNext("Hello, world")
observer.onCompleted()
return Disposables.create {}
}.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
這里, 你可以更細(xì)致的看到整個(gè)事件的全過(guò)程. 其中<String>
表示事件的元素類型.
一共步驟就只有4步, 創(chuàng)建, 發(fā)送事件, 發(fā)送結(jié)束標(biāo)記, 處理 dispose
你可能會(huì)對(duì) create 里面的observer
感到困惑, 為何這里的是觀察者, 明明創(chuàng)建的是一個(gè)可觀察對(duì)象? 你只需要明白, 可觀察者在獲取到事件后, 他并不是自己處理, 而是將這個(gè)事件傳遞給觀察者.
當(dāng)你了解到這點(diǎn)之后, 你也許靈光一閃, 想到可以用來(lái)處理網(wǎng)絡(luò)事件
Observable<String?>.create { (observer) -> Disposable in
let task = URLSession.shared.dataTask(with: URL(string: "https://httpbin.org/get")!, completionHandler: { (data, _, error) in
if error != nil {
observer.onError(error!)
} else {
if data == nil {
observer.onNext(nil)
} else {
observer.onNext(String(data: data!, encoding: .utf8))
}
observer.onCompleted()
}
})
task.resume()
return Disposables.create {
task.cancel()
}
}.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
看到了嗎, 就這么簡(jiǎn)單. 你甚至可以通過(guò)使用 map 來(lái)改變事件內(nèi)容
例如
...與上面代碼一樣
.map{ $0 ?? "empty result" }
.subscribe { (event) in
print(event)
}.disposed(by: disposeBag)
你看到這里, 就表示你已經(jīng)基本上入門(mén)了, 接下來(lái), 你將會(huì)學(xué)習(xí)很多的操作符.