學過 Swift 的 同窗都知道, RxSwift 宛如 周董的 mojitogit
開始微醺github
再者上頭編程
爲何要學習 RxSwift ?json
卡蜜爾說過api
優雅,永不過期
數組
RxSwift 是 Rx 系列的 Swift 版本,相較於 OC 版的 ReactiveCocoa安全
它們有着殊途同歸之妙 函數響應式編程(FRP)
bash
什麼是 函數響應式編程 ?markdown
函數式編程的核心思想是 stateless
,無狀態。函數自己並不關心
外界輸入的值網絡
它只是在函數內部,將輸入的值 和 輸出的值 完成一種映射,即 input => output
好比:
func changeNum(input: Int) -> Int { return input * 3 } // changeNum 並不會對input 產生改變,只是將運算以後的值 輸出 複製代碼
無狀態
意味着函數自己,不會改變外部的狀態
,也不會改變輸入的值的狀態
Q
:將數組 [1,2,3,4] 裏的元素 都乘以2,返回新的數組
那麼通常的作法多是:
命令式編程
let array = [1,2,3,4] var newArray: [Int] = [] for item in array { var num = item num *= 2 newArray.append(num) } // [2,4,6,8] 複製代碼
命令式編程傾向於怎麼作
,具體是怎麼把每一個數都 * 2 的,那麼這裏 涉及到了 可變數組 newArray
若是某一個時刻
,newArray 被某個地方
改變了,都會達到 非預期
的效果
那麼函數式編程
會怎麼作呢?
let array = [1,2,3,4] let newArray = array.compactMap { return $0 * 2 } // [2,4,6,8] 複製代碼
函數式編程
和 申明式編程
的 思想大致一致
它們都只關注 作什麼
,而不是上面的 怎麼作?
函數式編程:傾向於作什麼,省去其繁瑣的過程,一種更爲 安全,直觀,易懂的編程方式
一種抽象的事件流
的異步編程
方法
好比
:用戶點擊一個按鈕,發送網絡請求,並將結果展現在label 上
這裏網絡請求是異步
的
想要展現在label 上,就要拿到 網絡請求的回調,進一步展現
造成事件流
寫法就是
button.rx.tap.subscribe(onNext: { // 點擊按鈕 HomeApi.getTitle().asObservable() // 發起網絡請求 .map { (title) -> String in // 拿到回調進行 map ("我是 \(title)") } .bind(to: (titleLabel?.rx.text)!) // 綁定給 label .disposed(by: rx.disposeBag) // 管理生命週期 }) 複製代碼
這麼一個較爲複雜的操做,且包含異步操做
的流程
在 RxSwift 的 調整以後,是否是更爲 簡單易懂
? 事件的分發以及維護,能夠在一個地方完成
大大提升了 代碼的可讀性
,以及維護成本
整個事件流
的過程 以下:
咱們不用去關心
序列中的 每個元素,是異步的 仍是同步的,線程是否安全
只有當咱們點擊按鈕
,發送信號
以後 ,代碼塊內的函數體纔會執行,整個一系列的事件流纔會產生
這使得咱們更加面向業務邏輯
而不是每一步的具體操做
那麼具體 RxSwift 是怎麼作到的呢?
喝完 mojito
你就知道了
對於初學者來講
RxSwift 的學習曲線確實很陡,它詮釋了什麼是面向協議編程
過程雖然晦澀
但道阻且長
真正的大師永遠懷着一顆學徒的心
在RxSwift 的世界裏,萬物皆 rx,處處是 序列
(sequence)
聽着像不像 iOS 的萬物皆對象
是的沒錯,咱們來看一下rx Reactive
的定義,首先引入眼簾的是 一個 叫 ReactiveCompatible
的協議
public protocol ReactiveCompatible { # 關聯協議 associatedtype ReactiveBase # rx 是 Reactive 類型,並將 ReactiveBase 傳入 static var rx: Reactive<ReactiveBase>.Type { get set } var rx: Reactive<ReactiveBase> { get set } } 複製代碼
Reactive 中 還對 ReactiveCompatible
進行了 協議的拓展,在這個擴展中,經過調用rx
,返回的是
Reactive 類型
或者Reactive實例
extension ReactiveCompatible { # Reactive 類型 public static var rx: Reactive<Self>.Type { get { return Reactive<Self>.self } } # Reactive 實例 public var rx: Reactive<Self> { get { return Reactive(self) } } } 複製代碼
在看一下 Reactive
的 實現,是一個 包含參數泛型 Base
的結構體
public struct Reactive<Base> { public let base: Base # 將 Reactive 的初始化調用者 設置爲 base public init(_ base: Base) { self.base = base } } 複製代碼
如上文中 點擊按鈕的 tap,即 button.rx.tap
, 類型就是 UIButton 類型,將 UIButton 的實例 設置爲 base
那麼想 實現 萬物皆rx
,只須要簡單的一步
extension NSObject: ReactiveCompatible { }
複製代碼
這樣就可讓全部繼承於 NSObjce
的對象,都遵循 ReactiveCompatible
協議,即 萬物皆rx
Observable 意味着,可被觀察的,也就是可觀察序列
,什麼是序列呢?
我理解的就是 具有 發出事件能力的 的一種信號
肚子餓了 -> 吃飯
肚子餓了
能夠做爲一個 可觀察序列,當咱們大腦感知到 肚子餓了,就能夠執行 去吃飯的操做
TextField 輸入 -> 顯示
TextField 輸入操做
能夠做爲一個序列,能夠監聽到 輸入的內容
接下來
就開始調試 mojito 了
看一個訂閱過程:
# 建立 let observable = Observable<String>.create { (observe) -> Disposable in # 發送 observe.onNext("mojito") return Disposables.create() } # 訂閱 observable.subscribe(onNext: { text in print(text) }).disposed(by: rx.disposeBag) // print "mojito" 複製代碼
Observable 可觀察序列
# Observable 繼承於 ObservableType public class Observable<Element> : ObservableType { # 資源的引用計數 +1 init() { _ = Resources.incrementTotal() } # 提供被訂閱的能力,由子類實現 public func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element { rxAbstractMethod() } # 將 Observable 類轉爲 Observable 實例 public func asObservable() -> Observable<Element> { return self } # 資源的引用計數 -1 deinit { _ = Resources.decrementTotal() } } 複製代碼
但是這裏並無看到序列的建立
,可是能夠看到一個 繼承關係: Observable<Element> : ObservableType
進入 ObservableType
# 協議 ObservableType,繼承於 ObservableConvertibleType public protocol ObservableType: ObservableConvertibleType { func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element } # ObservableType 擴展 extension ObservableType { # 提供了一個方法,將遵照 ObservableType 協議的對象 轉爲 Observable 實體 public func asObservable() -> Observable<Element> { return Observable.create { o in return self.subscribe(o) } } } 複製代碼
這裏仍是 沒有看到 訂閱的方法
還發現了 本身的爸爸是個協議
, 還有爺爺 ObservableConvertibleType
持着懷疑的態度,你又點進了 ObservableConvertibleType
# 也是個協議 public protocol ObservableConvertibleType { associatedtype Element typealias E = Element # 定義了一個方法,返回類型 Observable 可觀察序列 func asObservable() -> Observable<Element> } 複製代碼
可惡
既然這條路走不通,只能先不走了
哪裏跌倒
我就躺在哪裏
爲了達到萬物皆序列,咱們就要想辦法把全部事件轉化爲序列,asObservable() 即爲 RxSwift 的精髓
Observable.create()
點擊 creat ,豁然開朗,原來建立是經過 ObservableType
擴展,這也同時證實了 OOP
的好處,可擴展性強
ObservableType
像是一家名叫 ObservableType 的連鎖公司
它能夠在任何地方開個分店
實現本身公司的業務
# ObservableType 的擴展 extension ObservableType { public static func create(_ subscribe: @escaping (AnyObserver<Element>) -> Disposable) -> Observable<Element> { # 返回一個 匿名觀察序列,將 subscribe 逃逸閉包傳入 return AnonymousObservable(subscribe) } } 複製代碼
點擊 AnonymousObservable 進入
# 私有方法,外界沒法共享 # AnonymousObservable 繼承於 Producer final private class AnonymousObservable<Element>: Producer<Element> { typealias SubscribeHandler = (AnyObserver<Element>) -> Disposable # 定義 閉包屬性 let _subscribeHandler: SubscribeHandler # 將外界傳入的 閉包 保存 init(_ subscribeHandler: @escaping SubscribeHandler) { self._subscribeHandler = subscribeHandler } # 重寫 父類 Producer 提供的 run 方法 override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element { # 初始化匿名管道,傳入一個訂閱者 let sink = AnonymousObservableSink(observer: observer, cancel: cancel) let subscription = sink.run(self) return (sink: sink, subscription: subscription) } } 複製代碼
這裏又來了個 Producer
,點擊 Producer
# Producer 一樣繼承於 Observable class Producer<Element> : Observable<Element> { override init() { super.init() } # 這裏涉及到了線程,若是 CurrentThreadScheduler 指定了某個線程,那麼就會在指定線程中 執行 run # 不然 就會在當前線程中 執行 run # SinkDisposer實例 disposer,用來管理資源釋放 override func subscribe<Observer: ObserverType>(_ observer: Observer) -> Disposable where Observer.Element == Element { if !CurrentThreadScheduler.isScheduleRequired { // The returned disposable needs to release all references once it was disposed. let disposer = SinkDisposer() let sinkAndSubscription = self.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 } } } # 抽象方法,子類去實現,也就是匿名序列 AnonymousObservable func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element { rxAbstractMethod() } } 複製代碼
相信到此,你我都已經微醺了
你問我什麼是 序列
?
我 指 着 大 海 的 方 向
目前也只能先畫個圖,繼續觀望
小結
父類協議
的 creat 方法 ,生成 匿名觀察序列,即Producer
的子類AnonymousObservable
AnonymousObservable
保存外界傳入的 閉包Observable
抽象類,不實現方法Producer
類 實現 外界 subscribe 方法,並安排線程調度run
,由 AnonymousObservable
實現,父類 Producer
不負責ok ,繼續往下走
subscribe(onNext:) 訂閱
點擊 subscribe 進入,能夠看到 ObservableType 的擴展,提供了 subscribe.on
和 subscribe.onNext
2個方法
此處省略了 subscribe.on
extension ObservableType { ... public func subscribe(onNext: ((Element) -> Void)? = nil, onError: ((Swift.Error) -> Void)? = nil, onCompleted: (() -> Void)? = nil, onDisposed: (() -> Void)? = nil) -> Disposable { .... # 建立一個 匿名訂閱者 AnonymousObserver # 對外界傳入的執行閉包 進行保存 let observer = AnonymousObserver<Element> { event in switch event { case .next(let value): onNext?(value) case .error(let error): if let onError = onError { onError(error) } else { Hooks.defaultErrorHandler(callStack, error) } disposable.dispose() case .completed: onCompleted?() disposable.dispose() } } return Disposables.create( self.asObservable().subscribe(observer), disposable ) } } 複製代碼
這裏將 外界須要執行的 閉包,即本例中的 print(text)
,生成 AnonymousObserver
實例,傳入
self.asObservable().subscribe(observer)
也就是說,這個 AnonymousObserver
實例,會經過 Producer 調用 subscribe
而後由 子類 AnonymousObservable
,序列實例去調用 run
方法
來到文中,step 5 的 run
方法,以下
# 將外界 須要執行的閉包 ,以及 資源銷燬實例 生成的 元祖 傳入 AnonymousObservableSink # 生成 sink 管道實例,並執行 run # 將run 以後生成的實例,賦值給 subscription,並返回 subscription 和 sink override func run<Observer: ObserverType>(_ observer: Observer, cancel: Cancelable) -> (sink: Disposable, subscription: Disposable) where Observer.Element == Element { let sink = AnonymousObservableSink(observer: observer, cancel: cancel) let subscription = sink.run(self) return (sink: sink, subscription: subscription) } 複製代碼
進入 AnonymousObservableSink
final private class AnonymousObservableSink<Observer: ObserverType>: Sink<Observer>, ObserverType { typealias Element = Observer.Element typealias Parent = AnonymousObservable<Element> # 調用父類 Sink 的初始化方法,傳入 observer 和 cancel,即 管道 AnonymousObservableSink 持有 這2個屬性 override init(observer: Observer, cancel: Cancelable) { super.init(observer: observer, cancel: cancel) } func on(_ event: Event<Element>) { switch event { case .next: if load(self._isStopped) == 1 { return } self.forwardOn(event) case .error, .completed: if fetchOr(self._isStopped, 1) == 0 { self.forwardOn(event) self.dispose() } } } ### 熟悉的東西有沒有 # 這裏看到了 _subscribeHandler,也就是 發出的信號,保存的閉包 func run(_ parent: Parent) -> Disposable { return parent._subscribeHandler(AnyObserver(self)) } } 複製代碼
到這裏,咱們就會發現 sink
管道 它很重要
它持有了
要銷燬的實例,發出序列的閉包,執行序列的閉包
這裏的 AnyObserver(self) 是爲了 兼容傳入 閉包的類型, 本文對應的 是 String
複製代碼
那麼 火車序列 就開始發動了
,可是 怎麼響應? 下一步往哪開?
這就要看 AnyObserver(self)
,作了什麼,進入 AnyObserver, 查看init
public init<Observer: ObserverType>(_ observer: Observer) where Observer.Element == Element { self.observer = observer.on } 複製代碼
你會發現這裏的 self.observer
保存了 本身的 on 方法
也就是保存的了一個 function
即 會調用 step8 中 的 on
, 而後 去調用 父類Sink 的 forwardOn
# 父類 Sink class Sink<Observer: ObserverType> : Disposable { final func forwardOn(_ event: Event<Observer.Element>) { #if DEBUG self._synchronizationTracker.register(synchronizationErrorMessage: .default) defer { self._synchronizationTracker.unregister() } #endif if isFlagSet(self._disposed, 1) { return } # 訂閱者 self._observer.on(event) } } 複製代碼
在父類 forwardOn
中, 由訂閱者執行 on
事件
但是 訂閱者 AnonymousObserver
類有沒有 on
方法,只有 onCore
因此去 AnonymousObserver 的 父類中 ObserverBase
尋找
class ObserverBase<Element> : Disposable, ObserverType { private let _isStopped = AtomicInt(0) func on(_ event: Event<Element>) { switch event { case .next: if load(self._isStopped) == 0 { self.onCore(event) } case .error, .completed: if fetchOr(self._isStopped, 1) == 0 { self.onCore(event) } } } # 子類實現 func onCore(_ event: Event<Element>) { rxAbstractMethod() } } 複製代碼
最後 AnonymousObserver
調用本身的 onCore
執行 eventHandler
閉包
到此
整個執行的過程算是走完了
關於資源回收
的內容,後續文章會寫到
mojito 初體驗 結束
AnonymousObservable
保存 可觀察序列AnonymousObserve
保存 執行閉包SinkDisposer
以及 observer
實例 元祖Sink
管道Sink
處理事件,發出信號,響應序列簡單的流程圖以下
有了RxSwift ,平常開發就變得酣暢淋漓了,好比
tableView.rx.contentOffset.subscribe(onNext: { contentOffset in /// 修改透明度 }) .disposed(by: rx.disposeBag) 複製代碼
textField.rx.text.skip(1).subscribe(onNext: { (text) in print("輸入的是 : \(text!)") }) .disposed(by: rx.disposeBag) 複製代碼
self.messageBtn.rx.tap.subscribe(onNext: { in Navigator.push("") }) .disposed(by: rx.disposeBag) 複製代碼
# 這裏須要導入 RxDataSources dataSource = RxTableViewSectionedReloadDataSource(configureCell: { (_, tab, indexPath, item) -> UITableViewCell in let cell = tab.dequeue(Reusable.settingCell, for: indexPath) cell.bind(to: item) return cell }) # 或者 let items = Observable.just([ "Just", "Relay", "From", "Driver", "merge" ]) items.bind(to: tableView.rx.items) { (tableView,_,element) in let cell = self.tableView.dequeue(TestV.normalCell) cell?.textLabel?.text = element return cell! } .disposed(by: rx.disposeBag) 複製代碼
tableView.rx.itemSelected.subscribe(onNext: { indexPath in /// doSomething }) .disposed(by: rx.disposeBag) 複製代碼
extension Response { func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> T { let jsonString = String.init(data: data, encoding: .utf8) if let modelT = JSONDeserializer<T>.deserializeFrom(json: jsonString) { return modelT } return JSONDeserializer<T>.deserializeFrom(json: "{\"msg\":\"解析有誤\"}")! } } extension ObservableType where Element == Response { /// 註釋 public func mapHandyJsonModel<T: HandyJSON>(_ type: T.Type) -> Observable<T> { return flatMap { response -> Observable<T> in return Observable.just(response.mapHandyJsonModel(T.self)) } } } # 配合 Moya static func getTopList() -> Observable<HomeResponseModel> { return HomeApiProvider.rx.request(.Top).asObservable().mapHandyJsonModel(HomeResponseModel.self) } 複製代碼
Observable.zip(HomeApi.getTopList(), HomeApi.getRecommondList()).subscribe(onNext: { topResponse, recommodResponse in /// 數據處理 }).disposed(by: self.rx.disposeBag) 複製代碼
先介紹一點簡單的用法
後續會慢慢更新
RxSwift
熟悉了以後,會讓咱們的代碼變得 簡潔且優雅
它面向協議編程,咱們面向業務編程
RxSwift
須要慢慢品味
聽一遍 mojito
確定是不夠的
不說了
聽歌去了~
沒喝過 mojito
的 就從這裏開始吧~