RxSwift 是什么? 為什么要引入它?它有什么優(yōu)點儒飒、好處呢者蠕?
函數式編程:利用高階函數,即將函數作為其它函數的參數佩番。
響應式編程:關注于數據流及變化的傳播众旗。
概述
見名知意,RxSwift 是在 Apple 推出 Swift 后,針對 Swift 語言 ReactiveX 推出 Reactive Extensions 系列一個實現庫;除此之外趟畏,ReactiveX 還推出了 RxJava贡歧,RxAndroid,RxPHP 等蘊含類似思想的框架赋秀。
為什么要學習RxSwift?
我們知道 C 語言的面向過程,Objective-C利朵、C++ 面向對象編程, Java 的 Spring 框架提出了面向切面編程的思想,學習 RxSwift 不是學習如何使用第三方庫,而是學習一種編程思想--函數響應式編程;
Target Action
傳統實現方法:
button.addTarget(self, action: #selector(buttonTapped), for: .touchUpInside)
func buttonTapped() {
print("button Tapped")
}
通過 Rx 來實現:
button.rx.tap
.subscribe(onNext: {
print("button Tapped")
})
.disposed(by: disposeBag)
你不需要使用 Target Action猎莲,這樣使得代碼邏輯清晰可見绍弟。
代理
傳統實現方法:
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
scrollView.delegate = self
}
}
extension ViewController: UIScrollViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
print("contentOffset: \(scrollView.contentOffset)")
}
}
通過 Rx 來實現:
class ViewController: UIViewController {
...
override func viewDidLoad() {
super.viewDidLoad()
scrollView.rx.contentOffset
.subscribe(onNext: { contentOffset in
print("contentOffset: \(contentOffset)")
})
.disposed(by: disposeBag)
}
}
你不需要書寫代理的配置代碼,就能獲得想要的結果著洼。
通知
傳統實現方法:
var ntfObserver: NSObjectProtocol!
override func viewDidLoad() {
super.viewDidLoad()
ntfObserver = NotificationCenter.default.addObserver(
forName: .UIApplicationWillEnterForeground,
object: nil, queue: nil) { (notification) in
print("Application Will Enter Foreground")
}
}
deinit {
NotificationCenter.default.removeObserver(ntfObserver)
}
通過 Rx 來實現:
override func viewDidLoad() {
super.viewDidLoad()
NotificationCenter.default.rx
.notification(.UIApplicationWillEnterForeground)
.subscribe(onNext: { (notification) in
print("Application Will Enter Foreground")
})
.disposed(by: disposeBag)
}
你不需要去管理觀察者的生命周期樟遣,這樣你就有更多精力去關注業(yè)務邏輯。
4身笤、等待多個并發(fā)任務完成后處理結果
例如豹悬,需要將兩個網絡請求合并成一個,
通過 Rx 來實現:
/// 用 Rx 封裝接口
enum API {
/// 取得老師的詳細信息
static func teacher(teacherId: Int) -> Observable<Teacher> { ... }
/// 取得老師的評論
static func teacherComments(teacherId: Int) -> Observable<[Comment]> { ... }
}
/// 同時取得老師信息和老師評論
Observable.zip(
API.teacher(teacherId: teacherId),
API.teacherComments(teacherId: teacherId)
).subscribe(onNext: { (teacher, comments) in
print("獲取老師信息成功: \(teacher)")
print("獲取老師評論成功: \(comments.count) 條")
}, onError: { error in
print("獲取老師信息或評論失敗: \(error)")
})
.disposed(by: disposeBag)
這樣你可用寥寥幾行代碼來完成相當復雜的異步操作液荸。
Why use RxSwift?
A vast majority of the code we write involves responding to external events. When a user manipulates a control, we need to write an @IBAction handler to respond. We need to observe notifications to detect when the keyboard changes position. We must provide closures to execute when URL sessions respond with data. And we use KVO to detect changes to variables. All of these various systems makes our code needlessly complex. Wouldn't it be better if there was one consistent system that handled all of our call/response code? Rx is such a system.
RxSwift is the official implementation of Reactive Extensions (aka Rx), which exist for most major languages and platforms.
翻譯:
我們編寫的絕大多數代碼涉及對外部事件的響應瞻佛。當一個用戶操作控制,我們需要寫一個@IBAction處理器響應娇钱。當鍵盤改變位置時涤久,我們需要觀察通知來檢測涡尘。當URL會話響應數據時,必須提供閉包來執(zhí)行响迂。我們使用KVO的變化來檢測變量考抄。所有這些不同的系統使我們的代碼不必要的復雜。如果有一個一致的系統處理我們所有的呼叫/響應代碼蔗彤,這不是更好嗎川梅?Rx就是這樣一個系統。
RxSwift是官方實現的Reactive擴展正(又名Rx)然遏,存在的最主要的語言和平臺贫途。
RxSwift的優(yōu)點
- Composable 可組合,在設計模式中有一種模式叫做組合模式待侵,你可以方便的用不同的組合實現不同的類
- Reusable 代碼可重用丢早,原因很簡單,對應RxSwift秧倾,就是一堆Obserable
- Declarative 響應式的怨酝,因為狀態(tài)不可變,只有數據變化
- Understandable and concise 簡潔那先,容易理解农猬, 因為它抽象的了異步編程,使我們統一了代碼風格售淡。
- Stable 穩(wěn)定斤葱,因為RxSwift寫出的代碼,單元測試時分方便
- Less stateful “無”狀態(tài)性揖闸,因為對于響應式編程揍堕,你的應用程序就是一堆數據流
- Without leaks 沒有泄漏,因為資源管理非常簡單
響應式編程:ReactiveCocoa vs RxSwift 選誰好?
RAC是一個已經有著3年歷史的項目汤纸,從Objective-C時期開始衩茸,后來從3.0開始支持了swift(可以通過bridge在OC下使用),接著就完全停止了在Objective-C上的維護蹲嚣。RxSwift項目的時間短一些只有幾個月(作者寫的時間是15年),但是社區(qū)似乎充滿了動力祟牲。關于RxSwift有一件重要的事是項目是按照 ReactiveX這個組織的規(guī)定下開發(fā)的隙畜,并且所有其他語言的Rx項目也是一樣。如果學會了如何使用RxSwift说贝,再去學習Rx.Net, RxJava 或者 RxJS就是小菜一碟议惰,只是語言語法上的差異。這真的就是learn once, apply everywhere.
如果項目中有oc,就用ReactiveCocoa乡恕;
要是用沒有言询,就用RxSwift咯
RxSwift comprises five separate components depending on eachother in the following way:
1俯萎、RxSwift 中文文檔
https://github.com/beeth0ven/RxSwift-Chinese-Documentation
2、官網 Observable
http://reactivex.io/documentation/observable.html
3运杭、官網 Operators
http://reactivex.io/documentation/operators.html
4夫啊、官網 Subject
http://reactivex.io/documentation/subject.html
5、官網 Single
http://reactivex.io/documentation/single.html
6辆憔、官網 Scheduler
http://reactivex.io/documentation/scheduler.html
RxSwift 核心流程
- 觀察者(Observer)
- 被觀察者(Observable)
- 訂閱者(Subscriber) 事件的最終處理者
- 管道(Sink) Observer 和 Observable 溝通的橋梁
1 創(chuàng)建信號
2 訂閱信號
3 發(fā)送信號
/// MARK: - testDemo1
private func testDemo1() {
// 1.創(chuàng)建信號 observable
requestObservable = Observable.create { (subscriber) -> Disposable in
// 3.發(fā)送消息
self.count += 1
subscriber.on(.next("哈哈哈哈哈??\(self.count)"))
subscriber.on(.completed)
return Disposables.create()
}
// 2.訂閱信號
requestObservable?.subscribe(onNext: { (text) in
print("=== \(text)")
self.mapPassword.text = text
}).dispose()
}
我們重點關注:
create 閉包什么時候執(zhí)行撇眯,
subscribe 閉包又是什么時候執(zhí)行的
Observable 繼承體系
Observable的核心函數:
subscribe 訂閱操作, Observable 和 Observer 通過訂閱建立聯系,
Observable 好比水源, Observer 好比水龍頭(永遠開著的水龍頭)虱咧, 訂閱的過程就是在Observable 和 Observer 之間建立管道熊榛, 一旦建立管道即是永久性的,只要水源有誰腕巡, 水龍頭就會有水玄坦。
run 對用戶不可見,隱藏了大量的實現細節(jié)绘沉, 這個函數就是建立水管的過程
asObservable: 這個協議的存在使得Observable 的定義變得更加廣泛煎楣。
首先說一下繼承體系: AnonymousObservable -> Producer -> Observable -> ObservableType -> ObservableConvertibleType
每一層都只處理一點點事情,剩下的交給下一層處理
ObservableConvertibleType: 完全的抽象
ObservableType: 處理subscribe
Observable: 處理 asObservable
Producer: 重載subscribe
AnonymousObservable: 處理run
也就是說如果說如果我們要自定義一個Observable的話梆砸,通常只需要繼承Producer转质, 并實現run方法。AnonymousObservable做的事情也不多帖世,實現run方法休蟹,作為create閉包的持有者。
run方法涉及另外一個類AnonymousObservableSink,Sink作為Observer 和 Observable的銜接的橋梁日矫,之前還在想為什么叫做ObservableSink赂弓,現在想明白了。Sink本身遵守ObseverType協議哪轿,與此同時實現了run方法盈魁,雖然沒有實現subscribe方法,但是已經足夠了窃诉,這樣sink從某種程度來說也是Observable杨耙,通過sink就可以完成從Observable到Obsever的轉變。
Observer 繼承體系
核心語句
// Producer Class
override func subscribe<O : ObserverType>(_ observer: O) -> Disposable where O.E == Element {
if !CurrentThreadScheduler.isScheduleRequired {
// The returned disposable needs to release all references once it was disposed.
let disposer = SinkDisposer()
let sinkAndSubscription = run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
else {
return CurrentThreadScheduler.instance.schedule(()) { _ in
let disposer = SinkDisposer()
let sinkAndSubscription = self.run(observer, cancel: disposer)
disposer.setSinkAndSubscription(sink: sinkAndSubscription.sink, subscription: sinkAndSubscription.subscription)
return disposer
}
}
}
我們來看看run的邏輯
// AnonymousObservable Class
override func run<O : ObserverType>(_ observer: O, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where O.E == Element {
let sink = AnonymousObservableSink(observer: observer, cancel: cancel)
let subscription = sink.run(self)
return (sink: sink, subscription: subscription)
}
在進行訂閱的過程中飘痛,Producer
的subscribe :方法里面珊膜,通過
let sinkAndSubscription = self.run(observer, cancel: disposer)
這個核心語句
運行run()方法,通過實例AnonymousObservable
實現的run()
方法宣脉,調取AnonymousObservableSink
的run()
方法车柠,通過參數的形式,將自己傳給了Sink 類,observer 竹祷;因為Sink
類中持有一個observer 谈跛。 AnonymousObservableSink
的方法里面有
func run(_ parent: Parent) -> Disposable {
return parent._subscribeHandler(AnyObserver(self))
}
終于觸發(fā)subscribeHandler了,這里的subscribeHandler就是之前最開始的閉包塑陵。
Observable<String>.create { observer -> Disposable in
observer.onNext("hello")
return Disposables.create()
}
稍微解釋一下整個過程分為兩個階段:
Obsevable 構建階段感憾,這里使用create構造方法構造Obsevable,還有其他各種各樣的構造方法猿妈,這里不一一贅述吹菱。
subscribe 階段, Obsevable.subscribe ---> Obsevable.run ----> Sink.run ----> AnyObserver.On ----> Sink.on ----> Observer.On ---> Observer.OnCore ----> eventHandler