爲何要用RXSwift?倒不如說爲何要用ReactiveX,使用它有什麼好處html
ReactiveX所表明的是響應式函數編程,也就是說能夠經過可監聽序列和函數式編程,讓數據/事件流和異步任務可以更方便的序列化處理。簡單來講就是:git
複合 - Rx 就是複合的代名詞github
複用 - 由於它易複合編程
清晰 - 由於聲明都是不可變動的bash
易用 - 由於它抽象的了異步編程,使咱們統一了代碼風格網絡
穩定 - 由於 Rx 是徹底經過單元測試的閉包
函數式編程併發
須要咱們將函數做爲參數傳遞,或者做爲返回值返還。使咱們能夠經過組合不一樣的方法,以及不一樣的函數來獲取目標結果。異步
響應式編程 函數式編程
業內經典的實例就是ReactiveCocoa,它都敢叫Cocoa,足以說明它的強大之處,事實上,它就是KVO的一個靈活展現。不須要考慮調用順序,只須要知道考慮結果,相似於蝴蝶效應,產生一個事件,會影響不少東西,這些事件像流同樣的傳播出去,而後影響結果,借用面向對象的一句話,萬物皆是流。是把操做盡可能寫成一系列嵌套的函數或者方法調用。
函數響應式編程
是種編程範式。它是經過構建函數操做數據序列,而後對這些序列作出響應的編程方式。它結合了函數式編程以及響應式編程
數據綁定(訂閱)
將可監聽序列綁定到觀察者上,實現同步監聽。
Sequence(序列):把事件操做,能夠看作一個序列,每次的改變都是一個序列,如一個TextFiled中的文本改變
,一個按鈕的點擊
,或者一個網絡請求結束
等。
Obserable(監聽事件或可監聽序列):每一次對事件改變的處理。
Observer(觀察者響應事件):觀察事件(UI、數據)的改變。
nevet(發生事件):subscribe後面發生的哈哈,好理解吧,如構建函數裏面的onNext
,onError
, onCompleted
事件。
Disposable (釋放):釋放已經不在使用的監聽資源,手動dispose,自動DisposeBags。
Schedulers(調度器):實現線程的調度。
RXSwift把每個操做事件,看作一個序列
任何能夠響應事件的行爲都是觀察者
咱們的不少操做均可以用序列來表示,Observer用於描述產生的序列。
let numbers: Observable<Int> = Observable.create { observer -> Disposable in
observer.onNext(0)
observer.onNext(1)
observer.onNext(2)
observer.onNext(3)
observer.onCompleted()
return Disposables.create()
}複製代碼
觀察者是用來監聽事件,而後他須要對這個事件作出響應,如點擊按鈕後的彈出提示框
。
在RX中觀察者是在訂閱(subscribe)後,由 onNext
,onError
,onCompleted
的這些閉包構建出來的。
如何自定義觀察者?
自己RX已經提供了去實現觀察者的方法,自定義參考AnyObserver和Binder
**AnyObserver
能夠用來描述任意一種觀察者
用戶名提示語是否隱藏
usernameValid
.bind(to: usernameValidOutlet.rx.isHidden)
.disposed(by: disposeBag)
看做是,自定義觀察者
let observer: AnyObserver<Bool> = AnyObserver { [weak self] (event) in
switch event {
case .next(let isHidden):
self?.usernameValidOutlet.isHidden = isHidden
default:
break
}
}
usernameValid
.bind(to: observer)
.disposed(by: disposeBag) 複製代碼
**Binder
主要用於觀察UI事件,具有兩個特徵:
1.不會處理錯誤事件
2.確保綁定都是在給定 Scheduler 上執行(默認 MainScheduler)
let observer: Binder<Bool> = Binder(usernameValidOutlet) { (view, isHidden) in
它的響應事件只會處理event
view.isHidden = isHidden
}
usernameValid
.bind(to: observer)
.disposed(by: disposeBag)複製代碼
重點:觀察者複用
//是否隱藏
extension Reactive where Base: UIView {
public var isHidden: Binder<Bool> {
return Binder(self.base) { view, hidden in
view.isHidden = hidden
}
}
}複製代碼
//是否可點擊
extension Reactive where Base: UIControl {
public var isEnabled: Binder<Bool> {
return Binder(self.base) { control, value in
control.isEnabled = value
}
}
}複製代碼
//label的當前文本
extension Reactive where Base: UILabel {
public var text: Binder<String?> {
return Binder(self.base) { label, text in
label.text = text
}
}
}複製代碼
許多UI空間都存在這種特性,他們既是可被監聽的序列同時也是觀察者。
**AsyncSubject
若是訂閱前沒有任何元素,只會監聽訂閱後的最後一個元素
let disposeBag = DisposeBag()
let subject = AsyncSubject<String>()
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject.onNext("🐹")
subject.onCompleted()
輸出結果
Subscription: 1 Event: next(🐹)
Subscription: 1 Event: completed複製代碼
**PublishSubject
只監聽訂閱後的元素
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
輸出結果
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)複製代碼
**ReplaySubject(獲取所有元素,能夠添加設置條件,如指定元素和限制時間段內)
// 1.先判斷條件
// 2.subscribe前的內容:從後往前訂閱 subscribe後的內容:不受影響
let disposeBag = DisposeBag()
let subject = ReplaySubject<String>.create(bufferSize: 1)
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
輸出結果
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)複製代碼
**BehaviorSubject
//1.先判斷訂閱前是否有新的元素,若是沒有就採用初始化時的默認元素
//2.不影響訂閱後的元素
let disposeBag = DisposeBag()
let subject = BehaviorSubject(value: "🔴")
subject
.subscribe { print("Subscription: 1 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🐶")
subject.onNext("🐱")
subject
.subscribe { print("Subscription: 2 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🅰️")
subject.onNext("🅱️")
subject
.subscribe { print("Subscription: 3 Event:", $0) }
.disposed(by: disposeBag)
subject.onNext("🍐")
subject.onNext("🍊")
輸出結果
Subscription: 1 Event: next(🔴)
Subscription: 1 Event: next(🐶)
Subscription: 1 Event: next(🐱)
Subscription: 2 Event: next(🐱)
Subscription: 1 Event: next(🅰️)
Subscription: 2 Event: next(🅰️)
Subscription: 1 Event: next(🅱️)
Subscription: 2 Event: next(🅱️)
Subscription: 3 Event: next(🅱️)
Subscription: 1 Event: next(🍐)
Subscription: 2 Event: next(🍐)
Subscription: 3 Event: next(🍐)
Subscription: 1 Event: next(🍊)
Subscription: 2 Event: next(🍊)
Subscription: 3 Event: next(🍊)
複製代碼
**Variable
變量監聽(如今RXSwift5被棄用了)複製代碼
**ControlProperty
專門用於描述 UI 控件屬性的,它具備如下特徵:
1.不會產生 error 事件
2.必定在 MainScheduler 訂閱/監聽(主線程)
3.共享狀態變化複製代碼
操做符幫助咱們構建所須要的序列。
如何選擇合適的操做符?
beeth0ven.github.io/RxSwift-Chi…
Disposable - 管理綁定(訂閱)的生命週期
DisposeBag
清除包
takeUntil
自動取消訂閱
用於控制任務在哪一個線程或者隊列運行
rxData
1.子線程控制數據
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .userInitiated))
2.主線程監聽處理結果,刷新UI
.observeOn(MainScheduler.instance)
.subscribe(onNext: { [weak self] data in
self?.data = data
})
.disposed(by: disposeBag)複製代碼
使用 subscribeOn
咱們用 subscribeOn來決定數據序列的構建函數在哪一個 Scheduler 上運行。以上例子中,因爲獲取 Data
須要花很長的時間,因此用 subscribeOn 切換到 後臺 Scheduler 來獲取 Data
。這樣能夠避免主線程被阻塞。
使用 observeOn
咱們用 observeOn來決定在哪一個 Scheduler 監聽這個數據序列。以上例子中,經過使用 observeOn方法切換到主線程來監聽而且處理結果。
MainScheduler:主線程
SerialDispatchQueueScheduler:抽象了串行,執行串行任務的調度
ConcurrentDispatchQueueScheduler:抽象了並行,執行並行任務的調度
OperationQueueScheduler:抽象了NSOperationQueue,控制最大併發數量
最後
學習RXSwift是一個漫長的過程,可是熟練事後確定會對這些高階的編程思想有所理解,以上是我的理解,不足之處還望指出,但願多多支持。