? ? ? ?首先來對比一下常用的幾種架構,這里列舉三種,MVC,MVP,MVVM架構,MVC架構屬于最經典的一種架構,M相當于Model層,負責處理數據相關的操作,V屬于View層,負責各種UI的展示和用戶交互,C屬于Controller控制器,屬于協調M層和V層,對于簡單的項目來說,使用MVC架構模式已經綽綽有余,但是隨著項目的不斷變大,功能不斷增多,參與項目的人員的更替,會發現,大量的業務邏輯是放在C層,而且不同人的編程習慣不一樣,當復雜的業務邏輯加上龐大的功能劃分疊加在一起的時候,會發現我們的C層早已臃腫不堪,搖搖欲墜了,這個時候代碼想要前進,唯一的辦法就是替換當前架構模式。
? ? ? 這里就先引入MVP架構,百度一下會看到這樣一句話:MVP 是從經典的模式MVC演變而來,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數據,View負責顯示,這個架構其實是多出了一層(P層)來幫助C層處理業務邏輯,這樣做的好處顯而易見,C層肩上的擔子明顯輕了很多,而且很多業務邏輯可以丟到P層來處理,一般項目可以使用這中架構模式,但是隨著開發的腳步不斷向前邁進,你會發現P層和C層過于親密,頻繁的交互高度耦合,當我們的需求變更時,P層也更作開始大變更,對于大型項目或者拓展性要求較高的項目,MVP架構明顯不能完成勝任,接下來,我們一起看看今天的重點,MVVM架構模式。
? ? MVVM架構,繼續百度吧,MVVM(Model-View-ViewModel)框架的由來便是MVP(Model-View-Presenter)模式與WPF結合的應用方式時發展演變過來的一種新型架構框架。它立足于原有MVP框架并且把WPF的新特性糅合進去,以應對客戶日益復雜的需求變化。進一步百度WPF,可以看到在技術層面,WPF帶來了 諸如Binding、Dependency Property、Routed Events、Command、DataTemplate、ControlTemplate等新特性,其實說到底就是一種信號綁定數據的模式,所有的數據都在信號里面執行,再由信號傳遞出來,優點很明顯,低耦合,可重用,沒個人可以寫自己的ViewModel模塊而不影響別人的代碼。
之前一篇文章已經講了一部分的RAC用法,接下來我們繼續進入RAC的使用,當你掌握它之后,我敢相信你已經深深愛上了RAC,因為它太神奇了,來,干!!!!
應用場景: 當我們請求到數據后,如果幾個地方都需要用到這個數據,如何避免多次使用,但請求就只有一次?
// 1. 創建信號 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id_Nonnull subscriber) {
// 請求數據
NSLog(@"請求數據");
// 發送數據
[subscriber sendNext:@"發送數據"];
return nil;
}];
// 2.轉換信號
RACMulticastConnection *connection = [signal publish];
// 3.開始訂閱
[connection.signal subscribeNext:^(id? _Nullable x) {
NSLog(@"A處理數據%@",x);
}];
[connection.signal subscribeNext:^(id? _Nullable x) {
NSLog(@"B處理數據%@",x);
}];
// 連接
[connection connect];
應用場景二: RACComand,這個類極大的幫我們優化的開發過程中的邏輯,流程:發送指令--->接收指令--->請求數據--->發送數據---->訂閱數據(還可以監聽事件的執行狀態)
// 1.創建命令? ? RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal * _Nonnull(id? _Nullable input) {? ? ? ? // input: 就是下面的輸入的指令? ? ? ? NSLog(@"%@",input);? ? ? ? // 返回一個信號? ? ? ? return [RACSignal createSignal:^RACDisposable * _Nullable(id_Nonnull subscriber) {
// 發送數據
[subscriber sendNext:@"執行完命令后,產生的數據"];
// 《如果要監聽事件的狀態,必須執行事件完成狀態》
[subscriber sendCompleted];
return nil;
}];
}];
// 監聽事件: 獲取命令狀態
[command.executing subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"%@",x);
if ([x boolValue]) {
NSLog(@"正在執行");
} else {
NSLog(@"已經結束和還沒開始做");
}
}];
// 執行
RACSignal *signal = [command execute:@"執行"];
// 訂閱
[signal subscribeNext:^(id? _Nullable x) {
NSLog(@"接收到數據了,%@",x);
}];
應用場景三: 綁定:bind
// 1.創建信號
RACSubject *subject = [RACSubject subject];
// 2.綁定信號
RACSignal *bindSignal = [subject bind:^RACSignalBindBlock _Nonnull{
return ^RACSignal *(id value,BOOL *stop) {
// value 就是“發送原始數據”
NSLog(@"%@",value);
// 應用場景: 可以在這里做字典轉模型
// 返回空信號
//? ? ? ? ? ? return [RACSignal empty];
return [RACReturnSignal return:value];
};
}];
// 3. 訂閱信號
[bindSignal subscribeNext:^(id? _Nullable x) {
NSLog(@"%@",x);
}];
// 4.發送
[subject sendNext:@"發送原始數據"];
其他場景:
順序組合 : concat 比較類似于串行隊列
返回最后的信號 : then?
壓縮信號 : zip 只有當多個信號都有發送數據時才會調用
組合 : combineLatest 同時監聽多個信號
合并 : merge 任一信號發送數據就會執行,類似并行隊列
這里就不上代碼了,只需要知道有這些個類型,及用法,到時候根據需要自行百度就好。
最后,就如何結合MVVM實際用法,簡單談下方法,由于C層只要求展示UI和用戶交互外,可以處理非常簡單的邏輯外,其余的事情我們直接交給ViewModel層來處理,可以在ViewModel里面設置各種信號屬性,同時讓C層持有ViewModel作為屬性,在事件需要處理時,使用RACComand或者RACSubject或者RACSignal來將事件轉化成信號。
另外需要特別主要的是:
1.輸入框的信號(比如:讓ModelView的屬性變化通過RAC宏來綁定C層的輸入框的信號)
2.RAC宏的優越性