iOS RAC總結

orilme發表於2019-04-07

Demo

  1. ReactiveCocoa 簡介(作者、作用、為什麼要用)
  2. ReactiveCocoa 作用
  3. ReactiveCocoa 工作原理和程式設計思想
  4. ReactiveCocoa 框架思維導圖
  5. ReactiveCocoa 常見類
  6. ReactiveCocoa 常見巨集
  7. ReactiveCocoa 常見用法
  8. ReactiveCocoa 常見方法
  9. UI - Category(常用匯總)
  10. Foundation - Category (常用匯總)

1. ReactiveCocoa簡介

ReactiveCocoa(簡稱為RAC),是由Github開源的一個應用於iOS和OS開發的新框架,Cocoa是蘋果整套框架的簡稱,因此很多蘋果框架喜歡以Cocoa結尾。

2. ReactiveCocoa作用

談到RAC的作用,首先來看一下一般 iOS 工程的構建方法。 MVC,一個典型的 iOS 工程的構建形式,Model 呈現資料,View 呈現使用者介面,而 View Controller 調節它兩者之間的互動。

MVC.png

然而,雖然 View 和 View Controller 是技術上不同的元件,但它們幾乎總是成對的。 下面這張圖準確地描述了我們可能已經編寫的 MVC 程式碼。但它並沒有做太多事情來解決 iOS 應用中C層臃腫的的問題。在典型的 MVC 應用裡,許多邏輯被放在 View Controller 裡。它們中的一些確實屬於 View Controller,但更多的是所謂的“表示邏輯(presentation logic)”,以 MVVM 的術語來說,就是那些將 Model 資料轉換為 View 可以呈現的東西的事情,例如將一個 NSDate 轉換為一個格式化過的 NSString。 [圖片上傳失敗...(image-ae0a0-1547395819243)] 我們圖解裡缺少某些東西,那些使我們可以把所有表示邏輯放進去的東西。我們打算將其稱為 “View Model” —— 它位於 View/Controller 與 Model 之間:

MVVM.png
MVVM.png

這個圖解準確地描述了什麼是 MVVM:一個 MVC 的增強版,我們正式連線了檢視和控制器,並將表示邏輯從 Controller 移出放到一個新的物件裡,即 View Model。MVVM 本質上就是一個精心優化的 MVC 架構。對我們來說,就是它能減少 ViewController 的複雜性並使得表示邏輯更易於測試

RAC的作用就在於它提供了很好的API可以很好的配合了MVVM的使用。 在我們iOS開發過程中,當某些事件響應的時候,需要處理某些業務邏輯,這些事件都用不同的方式來處理。比如按鈕的點選使用action,ScrollView滾動使用delegate,屬性值改變使用KVO等系統提供的方式。其實這些事件,都可以通過RAC處理。 ReactiveCocoa為事件提供了很多處理方法,而且利用RAC處理事件很方便,可以把要處理的事情,和監聽的事情的程式碼放在一起,這樣非常方便我們管理,就不需要跳到對應的方法裡。非常符合我們開發中高聚合,低耦合的思想。

3. ReactiveCocoa工作原理和程式設計思想

RAC工作原理.png

  • ReactiveCocoa程式設計思想:

    • 函數語言程式設計: 百度百科: 簡單說,"函數語言程式設計"是一種"程式設計正規化"(programming paradigm),也就是如何編寫程式的方法論。它屬於"結構化程式設計"的一種,主要思想是把運算過程儘量寫成一系列巢狀的函式呼叫。 函數語言程式設計思想:是把操作儘量寫成一系列巢狀的函式或者方法呼叫。 函數語言程式設計特點:每個方法必須有返回值(本身物件),把函式或者Block當做引數,block引數(需要操作的值)block返回值(操作結果)。 在RAC程式碼塊的複用。也就是訊號量的複用。

    • 響應式程式設計: 百度百科:響應式程式設計是一種面向資料流和變化傳播的程式設計正規化。這意味著可以在程式語言中很方便地表達靜態或動態的資料流,而相關的計算模型會自動將變化的值通過資料流進行傳播。 響應式程式設計思想:不需要考慮呼叫順序,只需要知道考慮結果,類似於蝴蝶效應,產生一個事件,會影響很多東西,這些事件像流一樣的傳播出去,然後影響結果,借用物件導向的一句話,萬物皆是流。 關於響應式程式設計,RAC將我們關注的點放到繫結。每一步都在操作和處理資料,但卻把操作點從以前的資料本身轉移到函式方法上邊去。將變數之間建立繫結,這就是響應式程式設計的內容。

    ReactiveCocoa被描述為函式響應式程式設計(FRP)框架。 以後使用RAC解決問題,就不需要考慮呼叫順序,直接考慮結果,把每一次操作都寫成一系列巢狀的方法中,使程式碼高聚合,方便管理。

  • 操作思想

    • 運用的是Hook(鉤子)思想,Hook是一種用於改變API(應用程式程式設計介面:方法)執行結果的技術.
    • Hook用處:截獲API呼叫的技術。
    • Hook原理:在每次呼叫一個API返回結果之前,先執行你自己的方法,改變結果的輸出。

4. ReactiveCocoa思維導圖

ReactiveCocoa.png

5. ReactiveCocoa常見類

學習框架首先搞清楚框架中常用的類,在RAC中最核心的類RACSiganl。

  • RACSiganl:訊號類,一般表示將來有資料傳遞,只要有資料改變,訊號內部接收到資料,就會馬上發出資料。
    RACEmptySignal :空訊號,用來實現 RACSignal 的 +empty 方法;
    RACReturnSignal :一元訊號,用來實現 RACSignal 的 +return: 方法;
    RACDynamicSignal :動態訊號,使用一個 block - 來實現訂閱行為,我們在使用 RACSignal 的 +createSignal: 方法時建立的就是該類的例項;
    RACErrorSignal :錯誤訊號,用來實現 RACSignal 的 +error: 方法;
    RACChannelTerminal :通道終端,代表 RACChannel 的一個終端,用來實現雙向繫結。

    注意:訊號類(RACSiganl),只是表示當資料改變時,訊號內部會發出資料,它本身不具備傳送訊號的能力,而是交給內部一個訂閱者去發出。 預設一個訊號都是冷訊號,也就是值改變了,也不會觸發,只有訂閱了這個訊號,這個訊號才會變為熱訊號,值改變了才會觸發。 如何訂閱訊號:呼叫訊號RACSignal的subscribeNext就能訂閱

  • RACSubscriber:表示訂閱者的意思,用於傳送訊號,這是一個協議

  • RACDisposable:用於取消訂閱或者清理資源,當訊號傳送完成或者傳送錯誤的時候,就會自動觸發它。
    RACSerialDisposable :作為 disposable 的容器使用,可以包含一個 disposable 物件,並且允許將這個 disposable 物件通過原子操作交換出來
    RACKVOTrampoline :代表一次 KVO 觀察,並且可以用來停止觀察
    RACCompoundDisposable :它可以包含多個 disposable 物件,並且支援手動新增和移除 disposable 物件
    RACScopedDisposable :當它被 dealloc 的時候呼叫本身的 -dispose 方法。

  • RACSubject
    RACSubject:訊號提供者,自己可以充當訊號,又能傳送訊號 使用場景:通常用來代替代理,有了它,就不必要定義代理了
    RACReplaySubject:重複提供訊號類,RACSubject的子類
    RACGroupedSignal :分組訊號,用來實現 RACSignal 的分組功能
    RACBehaviorSubject:重演最後值的訊號,當被訂閱時,會向訂閱者傳送它最後接收到的值
    RACReplaySubject:重演訊號,儲存傳送過的值,當被訂閱時,會向訂閱者重新傳送這些值

    RACReplaySubject與RACSubject區別: RACReplaySubject可以先傳送訊號,在訂閱訊號,RACSubject就不可以。

    使用場景
    使用場景一:如果一個訊號每被訂閱一次,就需要把之前的值重複傳送一遍,使用重複提供訊號類。
    使用場景二:可以設定capacity數量來限制快取的value的數量,即只緩充最新的幾個值

  • RACSequence:RAC中的集合類,用於代替NSArray,NSDictionary,可以使用它來快速遍歷陣列和字典

  • RACCommand:RAC中用於處理事件的類,可以把事件如何處理,事件中的資料如何傳遞,包裝到這個類中,他可以很方便的監控事件的執行過程。
    使用場景:監聽按鈕點選,網路請求

  • RACMulticastConnection:用於當一個訊號,被多次訂閱時,為了保證建立訊號時,避免多次呼叫建立訊號中的block,造成副作用,可以使用這個類處理。
    使用注意:RACMulticastConnection通過RACSignal的-publish或者-muticast:方法建立

  • RACTuple:元組類,類似NSArray,用來包裝值

  • RACScheduler:RAC中的佇列,用GCD封裝的
    RACImmediateScheduler:立即執行排程的任務,這是唯一一個支援同步執行的排程器
    RACQueueScheduler :一個抽象的佇列排程器,在一個 GCD 序列列隊中非同步排程所有任務
    RACTargetQueueScheduler :繼承自 RACQueueScheduler ,在一個以一個任意的 GCD 佇列為 target 的序列佇列中非同步排程所有任務
    RACSubscriptionScheduler :一個只用來排程訂閱的排程器

  • RACUnit :表⽰stream不包含有意義的值,也就是看到這個,可以直接理解為nil

  • RACEvent: 把資料包裝成訊號事件(signal event)。它主要通過RACSignal的-materialize來使用

6. ReactiveCocoa常見巨集

RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用於給某個物件的某個屬性繫結
RACObserve(self, name):監聽某個物件的某個屬性,返回的是訊號
RACTuplePack:把資料包裝成RACTuple(元組類)
RACTupleUnpack:把RACTuple(元組類)解包成對應的資料

7. ReactiveCocoa常見用法

rac_signalForSelector:用於替代代理。
rac_valuesAndChangesForKeyPath:代替KVO,用於監聽某個物件的屬性改變
rac_signalForControlEvents:用於監聽某個事件
rac_addObserverForName:用於監聽某個通知
rac_textSignal:監聽文字框文字改變
rac_liftSelector:withSignalsFromArray:Signals:當傳入的Signals(訊號陣列),每一個signal都至少sendNext過一次,就會去觸發第一個selector引數的方法。 (使用注意:幾個訊號,引數一的方法就幾個引數,每個引數對應訊號發出的資料。處理當介面有多次請求時,需要都獲取到資料時,才能展示介面:)

8. ReactiveCocoa常見方法

  • ReactiveCocoa操作方法之繫結

    • ReactiveCocoa操作的核心方法是bind(繫結),而且RAC中核心開發方式,也是繫結,之前的開發方式是賦值,而用RAC開發,應該把重心放在繫結,也就是可以在建立一個物件的時候,就繫結好以後想要做的事情,而不是等賦值之後在去做事情。
    • 例如:把資料展示到控制元件上,之前都是重寫控制元件的setModel方法,用RAC就可以在一開始建立控制元件的時候,就繫結好資料。
    • 在開發中很少使用bind方法,bind屬於RAC中的底層方法,RAC已經封裝了很多好用的其他方法,底層都是呼叫bind,用法比bind簡單(flattenMap、skip、take、takeUntilBlock、skipUntilBlock、distinctUntilChanged等function都用到了bind方法。我們可以發現很多地方都繼承和重寫bind方法).
    • 修改bindBlock 從而做到修改返回
  • ReactiveCocoa操作方法之對映
    Map:把源訊號的值對映成一個新的值
    flattenMap:把源訊號的內容對映成一個新的訊號,訊號可以是任意型別。
    FlatternMap和Map的區別
    1.FlatternMap中的Block返回訊號。
    2.Map中的Block返回物件。
    3.開發中,如果訊號發出的值不是訊號,對映一般使用Map
    4.開發中,如果訊號發出的值是訊號,對映一般使用FlatternMap。

  • ReactiveCocoa操作方法之組合
    concat:按一定順序拼接訊號,當多個訊號發出的時候,有順序的接收訊號
    then:用於連線兩個訊號,當第一個訊號完成,才會連線then返回的訊號 merge:把多個訊號合併為一個訊號,任何一個訊號有新值的時候就會呼叫
    zipWith:把兩個訊號壓縮成一個訊號,只有當兩個訊號同時發出訊號內容時,並且把兩個訊號的內容合併成一個元組,才會觸發壓縮流的next事件
    combineLatest:將多個訊號合併起來,並且拿到各個訊號的最新的值,必須每個合併的signal至少都有過一次sendNext,才會觸發合併的訊號
    reduce(聚合):用於訊號發出的內容是元組,把訊號發出元組的值聚合成一個值

  • ReactiveCocoa操作方法之過濾
    filter:過濾,每次訊號發出,會先執行過濾條件判斷
    ignore:內部呼叫filter過濾,忽略掉ignore的值
    distinctUntilChanged:當上一次的值和當前的值有明顯的變化就會發出訊號,否則會被忽略掉
    take:從開始一共取N次的訊號
    takeLast:取最後N次的訊號,前提條件,訂閱者必須呼叫完成,因為只有完成,就知道總共有多少訊號
    takeUntil:(RACSignal *):獲取訊號直到某個訊號執行完成
    skip:(NSUInteger):跳過幾個訊號,不接受
    switchToLatest:用於signalOfSignals(訊號的訊號),有時候訊號也會發出訊號,會在signalOfSignals中,獲取signalOfSignals傳送的最新訊號

  • 執行順序
    doNext: 執行Next之前,會先執行這個Block
    doCompleted: 執行sendCompleted之前,會先執行這個Block

  • ReactiveCocoa操作方法之時間
    timeout:超時,可以讓一個訊號在一定的時間後,自動報錯
    interval(定時):每隔一段時間發出訊號
    delay: 延遲傳送next

  • ReactiveCocoa操作方法之重複
    retry(重試) :只要失敗,就會重新執行建立訊號中的block,直到成功
    replay(重放):當一個訊號被多次訂閱,反覆播放內容
    throttle(節流):當某個訊號傳送比較頻繁時,可以使用節流,在某一段時間不傳送訊號內容,過了一段時間獲取訊號的最新內容發出

  • ReactiveCocoa操作方法之執行緒
    deliverOn: 內容傳遞切換到制定執行緒中,副作用在原來執行緒中,把在建立訊號時block中的程式碼稱之為副作用
    subscribeOn: 內容傳遞和副作用都會切換到制定執行緒中

9. UI - Category(常用匯總)

  • rac_prepareForReuseSignal: 需要複用時用
    相關UI: MKAnnotationView、UICollectionReusableView、UITableViewCell、UITableViewHeaderFooterView
  • rac_buttonClickedSignal:點選事件觸發訊號
    相關UI:UIActionSheet、UIAlertView
  • rac_command:button類、重新整理類相關命令替換
    相關UI:UIBarButtonItem、UIButton、UIRefreshControl
  • rac_signalForControlEvents: control event 觸發
    相關UI:UIControl
  • rac_gestureSignal UIGestureRecognizer 事件處理訊號
    相關UI:UIGestureRecognizer
  • rac_imageSelectedSignal 選擇圖片的訊號
    相關UI:UIImagePickerController
  • rac_textSignal
    相關UI:UITextField、UITextView
  • 可實現雙向繫結的相關API
    • rac_channelForControlEvents: key: nilValue:
      相關UI:UIControl類
    • rac_newDateChannelWithNilValue:
      相關UI:UIDatePicker
    • rac_newSelectedSegmentIndexChannelWithNilValue:
      相關UI:UISegmentedControl
    • rac_newValueChannelWithNilValue:
      相關UI:UISlider、UIStepper
    • rac_newOnChannel
      相關UI:UISwitch
    • rac_newTextChannel
      相關UI:UITextField

10. Foundation - Category (常用匯總)

  1. NSArray
    rac_sequence 訊號集合
  2. NSData
    rac_readContentsOfURL: options: scheduler: 比oc多出執行緒設定
  3. NSDictionary
    rac_sequence 不解釋
    rac_keySequence key 集合
    rac_valueSequence value 集合
  4. NSEnumerator
    rac_sequence 不解釋
  5. NSFileHandle
    rac_readInBackground 見名知意
  6. NSIndexSet
    rac_sequence 不解釋
  7. NSInvocation
    rac_setArgument: atIndex: 設定引數
    rac_argumentAtIndex 取某個引數
    rac_returnValue 所關聯方法的返回值
  8. NSNotificationCenter
    rac_addObserverForName: object:註冊通知
  9. NSObject
    rac_willDeallocSignal 物件銷燬時發動的訊號
    rac_description debug用
    rac_observeKeyPath: options: observer: block:監聽某個事件
    rac_liftSelector: withSignals: 全部訊號都next在執行
    rac_signalForSelector: 代替某個方法
    rac_signalForSelector:(SEL)selector fromProtocol:代替代理
  10. NSOrderedSet
    rac_sequence 不解釋
  11. NSSet
    rac_sequence 不解釋
  12. NSString
    rac_keyPathComponents 獲取一個路徑所有的部分
    rac_keyPathByDeletingLastKeyPathComponent 刪除路徑最後一部分
    rac_keyPathByDeletingFirstKeyPathComponent 刪除路徑第一部分
    rac_sequence 不解釋 (character)
    rac_readContentsOfURL: usedEncoding: scheduler: 比之OC多執行緒呼叫
  13. NSURLConnection
    rac_sendAsynchronousRequest 發起非同步請求
  14. NSUserDefaults
    rac_channelTerminalForKey 用於雙向繫結,此乃一端

參考文章:
最快讓你上手ReactiveCocoa之進階篇
iOS ReactiveCocoa 最全常用API整理
Introduction to MVVM

文章推薦:
ReactiveCocoa & MVVM 學習總結一
學習ReactiveCocoa教程