iOS ReactiveCocoa 基礎(chǔ)

  1. ReactiveCocoa 簡介(作者、作用、為什么要用)
  2. ReactiveCocoa 作用
  3. ReactiveCocoa 工作原理和編程思想
  4. ReactiveCocoa 框架思維導(dǎo)圖
  5. ReactiveCocoa 常見類
  6. ReactiveCocoa 常見宏
  7. ReactiveCocoa 常見用法
  8. ReactiveCocoa 常見方法
  9. UI - Category(常用匯總)
  10. Foundation - Category (常用匯總)

1. ReactiveCocoa簡介

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

2. ReactiveCocoa作用

談到RAC的作用,首先來看一下一般 iOS 工程的構(gòu)建方法。
MVC,一個典型的 iOS 工程的構(gòu)建形式,Model 呈現(xiàn)數(shù)據(jù),View 呈現(xiàn)用戶界面,而 View Controller 調(diào)節(jié)它兩者之間的交互。

MVC.png

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

MVVM.png

MVVM.png

這個圖解準確地描述了什么是 MVVM:一個 MVC 的增強版,我們正式連接了視圖和控制器,并將表示邏輯從 Controller 移出放到一個新的對象里,即 View Model。MVVM 本質(zhì)上就是一個精心優(yōu)化的 MVC 架構(gòu)。對我們來說,就是它能減少 ViewController 的復(fù)雜性并使得表示邏輯更易于測試。

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

3. ReactiveCocoa工作原理和編程思想

RAC工作原理.png
  1. ReactiveCocoa編程思想:

    • 函數(shù)式編程:
      百度百科: 簡單說,"函數(shù)式編程"是一種"編程范式"(programming paradigm),也就是如何編寫程序的方法論。它屬于"結(jié)構(gòu)化編程"的一種,主要思想是把運算過程盡量寫成一系列嵌套的函數(shù)調(diào)用。
      函數(shù)式編程思想:是把操作盡量寫成一系列嵌套的函數(shù)或者方法調(diào)用。
      函數(shù)式編程特點:每個方法必須有返回值(本身對象),把函數(shù)或者Block當做參數(shù),block參數(shù)(需要操作的值)block返回值(操作結(jié)果)。
      在RAC代碼塊的復(fù)用。也就是信號量的復(fù)用。

    • 響應(yīng)式編程:
      百度百科:響應(yīng)式編程是一種面向數(shù)據(jù)流和變化傳播的編程范式。這意味著可以在編程語言中很方便地表達靜態(tài)或動態(tài)的數(shù)據(jù)流,而相關(guān)的計算模型會自動將變化的值通過數(shù)據(jù)流進行傳播。
      響應(yīng)式編程思想:不需要考慮調(diào)用順序,只需要知道考慮結(jié)果,類似于蝴蝶效應(yīng),產(chǎn)生一個事件,會影響很多東西,這些事件像流一樣的傳播出去,然后影響結(jié)果,借用面向?qū)ο蟮囊痪湓?,萬物皆是流。
      關(guān)于響應(yīng)式編程,RAC將我們關(guān)注的點放到綁定。每一步都在操作和處理數(shù)據(jù),但卻把操作點從以前的數(shù)據(jù)本身轉(zhuǎn)移到函數(shù)方法上邊去。將變量之間建立綁定,這就是響應(yīng)式編程的內(nèi)容。

    ReactiveCocoa被描述為函數(shù)響應(yīng)式編程(FRP)框架。
    以后使用RAC解決問題,就不需要考慮調(diào)用順序,直接考慮結(jié)果,把每一次操作都寫成一系列嵌套的方法中,使代碼高聚合,方便管理。

  2. 操作思想

    • 運用的是Hook(鉤子)思想,Hook是一種用于改變API(應(yīng)用程序編程接口:方法)執(zhí)行結(jié)果的技術(shù).
    • Hook用處:截獲API調(diào)用的技術(shù)。
    • Hook原理:在每次調(diào)用一個API返回結(jié)果之前,先執(zhí)行你自己的方法,改變結(jié)果的輸出。

4. ReactiveCocoa思維導(dǎo)圖

ReactiveCocoa.png

5. ReactiveCocoa常見類

學(xué)習(xí)框架首先搞清楚框架中常用的類,在RAC中最核心的類RACSiganl。

  • RACSiganl:信號類,一般表示將來有數(shù)據(jù)傳遞,只要有數(shù)據(jù)改變,信號內(nèi)部接收到數(shù)據(jù),就會馬上發(fā)出數(shù)據(jù)。

    RACEmptySignal :空信號,用來實現(xiàn) RACSignal 的 +empty 方法;
    RACReturnSignal :一元信號,用來實現(xiàn) RACSignal 的 +return: 方法;
    RACDynamicSignal :動態(tài)信號,使用一個 block - 來實現(xiàn)訂閱行為,我們在使用 RACSignal 的 +createSignal: 方法時創(chuàng)建的就是該類的實例;
    RACErrorSignal :錯誤信號,用來實現(xiàn) RACSignal 的 +error: 方法;
    RACChannelTerminal :通道終端,代表 RACChannel 的一個終端,用來實現(xiàn)雙向綁定。

    注意

    信號類(RACSiganl),只是表示當數(shù)據(jù)改變時,信號內(nèi)部會發(fā)出數(shù)據(jù),它本身不具備發(fā)送信號的能力,而是交給內(nèi)部一個訂閱者去發(fā)出。
    默認一個信號都是冷信號,也就是值改變了,也不會觸發(fā),只有訂閱了這個信號,這個信號才會變?yōu)闊嵝盘枺蹈淖兞瞬艜|發(fā)。
    如何訂閱信號:調(diào)用信號RACSignal的subscribeNext就能訂閱

  • RACSubscriber:表示訂閱者的意思,用于發(fā)送信號,這是一個協(xié)議

  • RACDisposable:用于取消訂閱或者清理資源,當信號發(fā)送完成或者發(fā)送錯誤的時候,就會自動觸發(fā)它。

    RACSerialDisposable :作為 disposable 的容器使用,可以包含一個 disposable 對象,并且允許將這個 disposable 對象通過原子操作交換出來
    RACKVOTrampoline :代表一次 KVO 觀察,并且可以用來停止觀察
    RACCompoundDisposable :它可以包含多個 disposable 對象,并且支持手動添加和移除 disposable 對象
    RACScopedDisposable :當它被 dealloc 的時候調(diào)用本身的 -dispose 方法。

  • RACSubject

    RACSubject:信號提供者,自己可以充當信號,又能發(fā)送信號
    使用場景:通常用來代替代理,有了它,就不必要定義代理了
    RACReplaySubject:重復(fù)提供信號類,RACSubject的子類
    RACGroupedSignal :分組信號,用來實現(xiàn) RACSignal 的分組功能
    RACBehaviorSubject :重演最后值的信號,當被訂閱時,會向訂閱者發(fā)送它最后接收到的值
    RACReplaySubject :重演信號,保存發(fā)送過的值,當被訂閱時,會向訂閱者重新發(fā)送這些值

    RACReplaySubject與RACSubject區(qū)別:
    RACReplaySubject可以先發(fā)送信號,在訂閱信號,RACSubject就不可以。

    使用場景:
    使用場景一:如果一個信號每被訂閱一次,就需要把之前的值重復(fù)發(fā)送一遍,使用重復(fù)提供信號類。
    使用場景二:可以設(shè)置capacity數(shù)量來限制緩存的value的數(shù)量,即只緩充最新的幾個值`

  • RACSequence:RAC中的集合類,用于代替NSArray,NSDictionary,可以使用它來快速遍歷數(shù)組和字典

  • RACCommand:RAC中用于處理事件的類,可以把事件如何處理,事件中的數(shù)據(jù)如何傳遞,包裝到這個類中,他可以很方便的監(jiān)控事件的執(zhí)行過程。

    使用場景:監(jiān)聽按鈕點擊,網(wǎng)絡(luò)請求

  • RACMulticastConnection:用于當一個信號,被多次訂閱時,為了保證創(chuàng)建信號時,避免多次調(diào)用創(chuàng)建信號中的block,造成副作用,可以使用這個類處理。

    使用注意:RACMulticastConnection通過RACSignal的-publish或者-muticast:方法創(chuàng)建

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

  • RACScheduler:RAC中的隊列,用GCD封裝的

    RACImmediateScheduler :立即執(zhí)行調(diào)度的任務(wù),這是唯一一個支持同步執(zhí)行的調(diào)度器
    RACQueueScheduler :一個抽象的隊列調(diào)度器,在一個 GCD 串行列隊中異步調(diào)度所有任務(wù)
    RACTargetQueueScheduler :繼承自 RACQueueScheduler ,在一個以一個任意的 GCD 隊列為 target 的串行隊列中異步調(diào)度所有任務(wù)
    RACSubscriptionScheduler :一個只用來調(diào)度訂閱的調(diào)度器

  • RACUnit :表?stream不包含有意義的值,也就是看到這個,可以直接理解為nil
  • RACEvent: 把數(shù)據(jù)包裝成信號事件(signal event)。它主要通過RACSignal的-materialize來使用

6. ReactiveCocoa常見宏

  1. RAC(TARGET, [KEYPATH, [NIL_VALUE]]):用于給某個對象的某個屬性綁定。
  2. RACObserve(self, name):監(jiān)聽某個對象的某個屬性,返回的是信號。
  3. RACTuplePack:把數(shù)據(jù)包裝成RACTuple(元組類)
  4. RACTupleUnpack:把RACTuple(元組類)解包成對應(yīng)的數(shù)據(jù)

7. ReactiveCocoa常見用法

  • rac_signalForSelector:用于替代代理。
  • rac_valuesAndChangesForKeyPath:代替KVO,用于監(jiān)聽某個對象的屬性改變。
  • rac_signalForControlEvents:用于監(jiān)聽某個事件。
  • rac_addObserverForName:用于監(jiān)聽某個通知。
  • rac_textSignal:監(jiān)聽文本框文字改變。
  • rac_liftSelector:withSignalsFromArray:Signals:當傳入的Signals(信號數(shù)組),每一個signal都至少sendNext過一次,就會去觸發(fā)第一個selector參數(shù)的方法。
    (使用注意:幾個信號,參數(shù)一的方法就幾個參數(shù),每個參數(shù)對應(yīng)信號發(fā)出的數(shù)據(jù)。處理當界面有多次請求時,需要都獲取到數(shù)據(jù)時,才能展示界面:)

8. ReactiveCocoa常見方法

  1. ReactiveCocoa操作的核心方法是bind(綁定),而且RAC中核心開發(fā)方式,也是綁定,之前的開發(fā)方式是賦值,而用RAC開發(fā),應(yīng)該把重心放在綁定,也就是可以在創(chuàng)建一個對象的時候,就綁定好以后想要做的事情,而不是等賦值之后在去做事情。
  2. 列如:把數(shù)據(jù)展示到控件上,之前都是重寫控件的setModel方法,用RAC就可以在一開始創(chuàng)建控件的時候,就綁定好數(shù)據(jù)。
  3. 在開發(fā)中很少使用bind方法,bind屬于RAC中的底層方法,RAC已經(jīng)封裝了很多好用的其他方法,底層都是調(diào)用bind,用法比bind簡單(flattenMap、skip、take、takeUntilBlock、skipUntilBlock、distinctUntilChanged等function都用到了bind方法。我們可以發(fā)現(xiàn)很多地方都繼承和重寫bind方法).
  4. 修改bindBlock 從而做到修改返回
  • ReactiveCocoa操作方法之映射

    Map:把源信號的值映射成一個新的值
    flattenMap:把源信號的內(nèi)容映射成一個新的信號,信號可以是任意類型。

    FlatternMap和Map的區(qū)別
    1.FlatternMap中的Block返回信號。
    2.Map中的Block返回對象。
    3.開發(fā)中,如果信號發(fā)出的值不是信號,映射一般使用Map
    4.開發(fā)中,如果信號發(fā)出的值是信號,映射一般使用FlatternMap。

  • ReactiveCocoa操作方法之組合

    concat:按一定順序拼接信號,當多個信號發(fā)出的時候,有順序的接收信號
    then:用于連接兩個信號,當?shù)谝粋€信號完成,才會連接then返回的信號
    merge:把多個信號合并為一個信號,任何一個信號有新值的時候就會調(diào)用
    zipWith:把兩個信號壓縮成一個信號,只有當兩個信號同時發(fā)出信號內(nèi)容時,并且把兩個信號的內(nèi)容合并成一個元組,才會觸發(fā)壓縮流的next事件
    combineLatest:將多個信號合并起來,并且拿到各個信號的最新的值,必須每個合并的signal至少都有過一次sendNext,才會觸發(fā)合并的信號
    reduce(聚合):用于信號發(fā)出的內(nèi)容是元組,把信號發(fā)出元組的值聚合成一個值

  • ReactiveCocoa操作方法之過濾

    filter:過濾,每次信號發(fā)出,會先執(zhí)行過濾條件判斷
    ignore:內(nèi)部調(diào)用filter過濾,忽略掉ignore的值
    distinctUntilChanged:當上一次的值和當前的值有明顯的變化就會發(fā)出信號,否則會被忽略掉
    take:從開始一共取N次的信號
    takeLast:取最后N次的信號,前提條件,訂閱者必須調(diào)用完成,因為只有完成,就知道總共有多少信號
    takeUntil:(RACSignal *):獲取信號直到某個信號執(zhí)行完成
    skip:(NSUInteger):跳過幾個信號,不接受
    switchToLatest:用于signalOfSignals(信號的信號),有時候信號也會發(fā)出信號,會在signalOfSignals中,獲取signalOfSignals發(fā)送的最新信號

  • 執(zhí)行順序

    doNext: 執(zhí)行Next之前,會先執(zhí)行這個Block
    doCompleted: 執(zhí)行sendCompleted之前,會先執(zhí)行這個Block

  • ReactiveCocoa操作方法之時間

    timeout:超時,可以讓一個信號在一定的時間后,自動報錯
    interval(定時):每隔一段時間發(fā)出信號
    delay: 延遲發(fā)送next

  • ReactiveCocoa操作方法之重復(fù)

retry(重試) :只要失敗,就會重新執(zhí)行創(chuàng)建信號中的block,直到成功
replay(重放):當一個信號被多次訂閱,反復(fù)播放內(nèi)容
throttle(節(jié)流):當某個信號發(fā)送比較頻繁時,可以使用節(jié)流,在某一段時間不發(fā)送信號內(nèi)容,過了一段時間獲取信號的最新內(nèi)容發(fā)出

  • ReactiveCocoa操作方法之線程

    deliverOn: 內(nèi)容傳遞切換到制定線程中,副作用在原來線程中,把在創(chuàng)建信號時block中的代碼稱之為副作用
    subscribeOn: 內(nèi)容傳遞和副作用都會切換到制定線程中

9. UI - Category(常用匯總)

  1. rac_prepareForReuseSignal: 需要復(fù)用時用
    相關(guān)UI: MKAnnotationView、UICollectionReusableView、UITableViewCell、UITableViewHeaderFooterView
  2. rac_buttonClickedSignal:點擊事件觸發(fā)信號
    相關(guān)UI:UIActionSheet、UIAlertView
  3. rac_command:button類、刷新類相關(guān)命令替換
    相關(guān)UI:UIBarButtonItem、UIButton、UIRefreshControl
  4. rac_signalForControlEvents: control event 觸發(fā)
    相關(guān)UI:UIControl
  5. rac_gestureSignal UIGestureRecognizer 事件處理信號
    相關(guān)UI:UIGestureRecognizer
  6. rac_imageSelectedSignal 選擇圖片的信號
    相關(guān)UI:UIImagePickerController
  7. rac_textSignal
    相關(guān)UI:UITextField、UITextView
  8. 可實現(xiàn)雙向綁定的相關(guān)API
    rac_channelForControlEvents: key: nilValue:
    相關(guān)UI:UIControl類
    rac_newDateChannelWithNilValue:
    相關(guān)UI:UIDatePicker
    rac_newSelectedSegmentIndexChannelWithNilValue:
    相關(guān)UI:UISegmentedControl
    rac_newValueChannelWithNilValue:
    相關(guān)UI:UISlider、UIStepper
    rac_newOnChannel
    相關(guān)UI:UISwitch
    rac_newTextChannel
    相關(guān)UI:UITextField

10. Foundation - Category (常用匯總)

  1. NSArray
    rac_sequence 信號集合
  2. NSData
    rac_readContentsOfURL: options: scheduler: 比oc多出線程設(shè)置
  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: 設(shè)置參數(shù)
    rac_argumentAtIndex 取某個參數(shù)
    rac_returnValue 所關(guān)聯(lián)方法的返回值
  8. NSNotificationCenter
    rac_addObserverForName: object:注冊通知
  9. NSObject
    rac_willDeallocSignal 對象銷毀時發(fā)動的信號
    rac_description debug用
    rac_observeKeyPath: options: observer: block:監(jiān)聽某個事件
    rac_liftSelector: withSignals: 全部信號都next在執(zhí)行
    rac_signalForSelector: 代替某個方法

rac_signalForSelector:(SEL)selector fromProtocol:代替代理

  1. NSOrderedSet
    rac_sequence 不解釋
  2. NSSet
    rac_sequence 不解釋
  3. NSString
    rac_keyPathComponents 獲取一個路徑所有的部分
    rac_keyPathByDeletingLastKeyPathComponent 刪除路徑最后一部分
    rac_keyPathByDeletingFirstKeyPathComponent 刪除路徑第一部分
    rac_sequence 不解釋 (character)
    rac_readContentsOfURL: usedEncoding: scheduler: 比之OC多線程調(diào)用
  4. NSURLConnection
    rac_sendAsynchronousRequest 發(fā)起異步請求
  5. NSUserDefaults
    rac_channelTerminalForKey 用于雙向綁定,此乃一端

Demo

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

文章推薦:
ReactiveCocoa & MVVM 學(xué)習(xí)總結(jié)一
學(xué)習(xí)ReactiveCocoa教程

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容