走進RXSwift

爲何要用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把每個操做事件,看作一個序列

任何能夠響應事件的行爲都是觀察者



如何學習

  • Observable - 可監聽序列:產生事件

咱們的不少操做均可以用序列來表示,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()
}複製代碼

  • Observer - 觀察者:響應事件

觀察者是用來監聽事件,而後他須要對這個事件作出響應,如點擊按鈕後的彈出提示框

在RX中觀察者是在訂閱(subscribe)後,由 onNextonErroronCompleted的這些閉包構建出來的。

如何自定義觀察者?

自己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
      }
  }
}複製代碼

  • Observable & Observer

許多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.共享狀態變化複製代碼

  • Operator - 選擇操做符:建立變化組合事件

操做符幫助咱們構建所須要的序列。

如何選擇合適的操做符?

beeth0ven.github.io/RxSwift-Chi…

  • Disposable - 管理綁定(訂閱)的生命週期

    DisposeBag 清除包

    takeUntil 自動取消訂閱

  • Schedulers - 線程隊列調配

用於控制任務在哪一個線程或者隊列運行

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是一個漫長的過程,可是熟練事後確定會對這些高階的編程思想有所理解,以上是我的理解,不足之處還望指出,但願多多支持。

相關文章
相關標籤/搜索