MVVM是一種編程思想 ,它的目標就是為了簡化Model層的Controller層,如果有必要viewModel層不可以添加多個,viewModel就是信息的中轉中,它負責著數(shù)據(jù)的獲取和分發(fā),相比較而言,MVVM比MVC有更明確的任務劃分,MVVM中VM就只負責數(shù)據(jù)請求,邏輯處理,V(控制器和View,在MVVM中將ViewController視作View)就只負責頁面展示和UI交互。
MVVM雖然有更明確的分工,但這樣的分工必然帶來復雜的數(shù)據(jù)通信問題,MV獲取到數(shù)據(jù)要將數(shù)據(jù)傳到V中去顯示,V中的一個事件要讓VM中做數(shù)據(jù)請求處理操作,其中涉及到了上到下的數(shù)據(jù)通信,下到上的數(shù)據(jù)通信,也有可能是跨多層級間的數(shù)據(jù)通信,還有不同線程間的數(shù)據(jù)通信,我們知道這些數(shù)據(jù)通信我們都可以通過代理,通知,block來解決,但會使可能會程序設計變得復雜而零亂,讓人想要放棄MVVM。有了響應式編程之后,不同層級之間的通信變得簡單,一個信號可以傳遞事件還可以攜帶我們想要傳遞的數(shù)據(jù),大大提高了編程效率,MVVM和響應式編程是一個黃金搭檔。
一個完整的信號由等待執(zhí)行的代碼塊和代碼塊執(zhí)行完成后返回的值組成,當一個信號管理者觸發(fā)了信號,信號會執(zhí)行代碼塊,并把結果返回。這兩部分缺一不可。一個沒有等待執(zhí)行的代碼塊或者是沒有監(jiān)測者的信號是沒有意義的,這樣的信號都不會被觸發(fā)。
[信號 filter:^BOOL(id?value){return 判斷結果]生成一個新的信號;
filter操作:對信號返回的值進行過濾,只有判斷結果滿足的情況下,新信號的subscribeNext方法才會返回值;
[信號 map:^BOOL(id?value){return 返回新值]生成一個返回新值的新信號;
map操作:對信號返回的值進行加工處理,新信號的subscribeNext方法將會返回這個新的值;
[信號 flattenMap:^id(id?x){return 返回一個信號]生成一個返回信號的新信號,同時還從內部信號發(fā)送事件到外部信號
flattenMap操作:將信號返回的值轉換成內部信號,同時還將內部信號返回的值轉作為該信號的返回值,新信號的subscribeNext方法將會直接返回這個內部信號的返回值;
[信號 doNext:^(id?x){附加操作}]當信號返回值的時候做一些附加操作(按鈕狀態(tài)更新,返回數(shù)據(jù)存儲),附加操作并不改變事件本身;
[信號combineLatest:@[信號1,信號2]
reduce:^id(信號1返回值,信號2返回值){
return返回新值;
}];生成一個返回新值的新信號;
combineLatest操作:對多個信號返回的值進行加工處理合并生,成一個新的返回值,新信號的subscribeNext方法將會返回這個新的值;
[RACSignal?createSignal:^RACDisposable?*(id?subscriber){return訂閱被取消時執(zhí)行一些清理工作}];方法創(chuàng)建了一個信號,當這個信號有subscriber時,block里的代碼就會執(zhí)行,你可以發(fā)送任意數(shù)量的next事件,或者用error\complete事件來終止。
subscription=[信號subscribeNext];所有RACSignal的訂閱方法都會返回一個RACDisposable實例,它允許你通過處置方法手動的移除訂閱,[subscription?dispose]
@weakify 宏定義允許你創(chuàng)建一個弱引用的影子變量,@strongify宏定義允許你創(chuàng)建一個前面使用@weakify傳遞的強引用變量。
concat:按一定順序拼接信號,當多個信號發(fā)出的時候,有順序的接收信號。第一個信號必須發(fā)送完成,第二個信號才會被激活
then一個信號訂閱執(zhí)行后,error\complete都會終止,通過then方法可以讓信號接收到error時會一直等待不終止,直到completed事件發(fā)出,然后訂閱者通過自己的block參數(shù)返回,這有效地將控制從一個信號傳遞給下一個。
then用于連接兩個信號,當?shù)谝粋€信號完成,才會連接then返回的信號,注意使用then,之前信號的值會被忽略掉,1、先過濾掉之前的信號發(fā)出的值。2.使用concat連接then返回的信號;只能接收到第二個信號的值,也就是then返回信號的值.
RACSubject信號中的信號
RACSubject使用步驟
1.創(chuàng)建信號 [RACSubject subject],跟RACSiganl不一樣,創(chuàng)建信號時沒有block。
2.訂閱信號 - (RACDisposable *)subscribeNext:(void (^)(id x))nextBlock
3.發(fā)送信號 sendNext:(id)value
RACSubject:底層實現(xiàn)和RACSignal不一樣。
1.調用subscribeNext訂閱信號,只是把訂閱者保存起來,并且訂閱者的nextBlock已經(jīng)賦值了。
2.調用sendNext發(fā)送信號,遍歷剛剛保存的所有訂閱者,一個一個調用訂閱者的nextBlock。
RACSignal,RACSubject,RACCommand的區(qū)別:
RACSignal:一般用來傳遞簡單的信號(按鈕,textView等已經(jīng)集成好的信號),而本身不能夠完成發(fā)送,需要借助UI事情或RACCommand才能完成信號的發(fā)送;
RACSubject(單工):當我們只單向傳遞一個信號,并且信號中要傳遞一個自定的對象時,創(chuàng)建RACSubject,自身可以完成發(fā)送;注,我們在使用RACSubject時,RACSubject是一個熱信號,當它的訂閱者被銷毀時并不會自動取消訂閱,當我們重新發(fā)送信號時,信號依然會發(fā)送跟之前的訂閱者,所以再我們不需要訂閱信號的時候,需要我們手動發(fā)送sendCommand來取消訂閱,否則會出現(xiàn)重復收到信號的情況。
RACCommand(半雙工):當我們需要一個信號能夠雙向傳值,即開始發(fā)從信號時傳入一個對象,信號訂閱者處理完信號后又返回一個對象;RACCommand的功能強大可以完成RACSignal,和RACSubject的功能,在項目中我們的很多信號都是通過按鈕點擊來發(fā)送的,RACSignalt和RACCommand都可以和按鈕點擊事件關聯(lián),所以當按鈕點擊發(fā)送信號時,即使是單向傳遞一個信號,也一般會選用RACSignal或RACCommand,只有當信號的發(fā)送由控制器的生命周期,代理事件來觸發(fā)時,且是單向傳遞才考慮使用RACSubject;