? ? ? ?首先來對比一下常用的幾種架構(gòu),這里列舉三種缩功,MVC晴及,MVP,MVVM架構(gòu)嫡锌,MVC架構(gòu)屬于最經(jīng)典的一種架構(gòu)虑稼,M相當于Model層琳钉,負責處理數(shù)據(jù)相關的操作,V屬于View層蛛倦,負責各種UI的展示和用戶交互歌懒,C屬于Controller控制器,屬于協(xié)調(diào)M層和V層溯壶,對于簡單的項目來說及皂,使用MVC架構(gòu)模式已經(jīng)綽綽有余,但是隨著項目的不斷變大茸塞,功能不斷增多躲庄,參與項目的人員的更替,會發(fā)現(xiàn)钾虐,大量的業(yè)務邏輯是放在C層,而且不同人的編程習慣不一樣笋庄,當復雜的業(yè)務邏輯加上龐大的功能劃分疊加在一起的時候效扫,會發(fā)現(xiàn)我們的C層早已臃腫不堪,搖搖欲墜了直砂,這個時候代碼想要前進菌仁,唯一的辦法就是替換當前架構(gòu)模式。
? ? ? 這里就先引入MVP架構(gòu)静暂,百度一下會看到這樣一句話:MVP 是從經(jīng)典的模式MVC演變而來济丘,它們的基本思想有相通的地方:Controller/Presenter負責邏輯的處理,Model提供數(shù)據(jù)洽蛀,View負責顯示,這個架構(gòu)其實是多出了一層(P層)來幫助C層處理業(yè)務邏輯摹迷,這樣做的好處顯而易見,C層肩上的擔子明顯輕了很多郊供,而且很多業(yè)務邏輯可以丟到P層來處理峡碉,一般項目可以使用這中架構(gòu)模式,但是隨著開發(fā)的腳步不斷向前邁進驮审,你會發(fā)現(xiàn)P層和C層過于親密鲫寄,頻繁的交互高度耦合,當我們的需求變更時疯淫,P層也更作開始大變更地来,對于大型項目或者拓展性要求較高的項目,MVP架構(gòu)明顯不能完成勝任熙掺,接下來未斑,我們一起看看今天的重點,MVVM架構(gòu)模式适掰。
? ? MVVM架構(gòu)颂碧,繼續(xù)百度吧荠列,MVVM(Model-View-ViewModel)框架的由來便是MVP(Model-View-Presenter)模式與WPF結(jié)合的應用方式時發(fā)展演變過來的一種新型架構(gòu)框架。它立足于原有MVP框架并且把WPF的新特性糅合進去载城,以應對客戶日益復雜的需求變化肌似。進一步百度WPF,可以看到在技術層面诉瓦,WPF帶來了 諸如Binding协怒、Dependency Property、Routed Events泻云、Command磕谅、DataTemplate、ControlTemplate等新特性煞聪,其實說到底就是一種信號綁定數(shù)據(jù)的模式斗躏,所有的數(shù)據(jù)都在信號里面執(zhí)行,再由信號傳遞出來昔脯,優(yōu)點很明顯啄糙,低耦合,可重用云稚,沒個人可以寫自己的ViewModel模塊而不影響別人的代碼隧饼。
之前一篇文章已經(jīng)講了一部分的RAC用法,接下來我們繼續(xù)進入RAC的使用静陈,當你掌握它之后燕雁,我敢相信你已經(jīng)深深愛上了RAC,因為它太神奇了鲸拥,來拐格,干!!!!
應用場景: 當我們請求到數(shù)據(jù)后,如果幾個地方都需要用到這個數(shù)據(jù)崩泡,如何避免多次使用禁荒,但請求就只有一次?
// 1. 創(chuàng)建信號 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? RACSignal *signal = [RACSignal createSignal:^RACDisposable * _Nullable(id_Nonnull subscriber) {
// 請求數(shù)據(jù)
NSLog(@"請求數(shù)據(jù)");
// 發(fā)送數(shù)據(jù)
[subscriber sendNext:@"發(fā)送數(shù)據(jù)"];
return nil;
}];
// 2.轉(zhuǎn)換信號
RACMulticastConnection *connection = [signal publish];
// 3.開始訂閱
[connection.signal subscribeNext:^(id? _Nullable x) {
NSLog(@"A處理數(shù)據(jù)%@",x);
}];
[connection.signal subscribeNext:^(id? _Nullable x) {
NSLog(@"B處理數(shù)據(jù)%@",x);
}];
// 連接
[connection connect];
應用場景二: RACComand,這個類極大的幫我們優(yōu)化的開發(fā)過程中的邏輯角撞,流程:發(fā)送指令--->接收指令--->請求數(shù)據(jù)--->發(fā)送數(shù)據(jù)---->訂閱數(shù)據(jù)(還可以監(jiān)聽事件的執(zhí)行狀態(tài))
// 1.創(chuàng)建命令? ? RACCommand *command = [[RACCommand alloc]initWithSignalBlock:^RACSignal * _Nonnull(id? _Nullable input) {? ? ? ? // input: 就是下面的輸入的指令? ? ? ? NSLog(@"%@",input);? ? ? ? // 返回一個信號? ? ? ? return [RACSignal createSignal:^RACDisposable * _Nullable(id_Nonnull subscriber) {
// 發(fā)送數(shù)據(jù)
[subscriber sendNext:@"執(zhí)行完命令后呛伴,產(chǎn)生的數(shù)據(jù)"];
// 《如果要監(jiān)聽事件的狀態(tài),必須執(zhí)行事件完成狀態(tài)》
[subscriber sendCompleted];
return nil;
}];
}];
// 監(jiān)聽事件: 獲取命令狀態(tài)
[command.executing subscribeNext:^(NSNumber * _Nullable x) {
NSLog(@"%@",x);
if ([x boolValue]) {
NSLog(@"正在執(zhí)行");
} else {
NSLog(@"已經(jīng)結(jié)束和還沒開始做");
}
}];
// 執(zhí)行
RACSignal *signal = [command execute:@"執(zhí)行"];
// 訂閱
[signal subscribeNext:^(id? _Nullable x) {
NSLog(@"接收到數(shù)據(jù)了谒所,%@",x);
}];
應用場景三: 綁定:bind
// 1.創(chuàng)建信號
RACSubject *subject = [RACSubject subject];
// 2.綁定信號
RACSignal *bindSignal = [subject bind:^RACSignalBindBlock _Nonnull{
return ^RACSignal *(id value,BOOL *stop) {
// value 就是“發(fā)送原始數(shù)據(jù)”
NSLog(@"%@",value);
// 應用場景: 可以在這里做字典轉(zhuǎn)模型
// 返回空信號
//? ? ? ? ? ? return [RACSignal empty];
return [RACReturnSignal return:value];
};
}];
// 3. 訂閱信號
[bindSignal subscribeNext:^(id? _Nullable x) {
NSLog(@"%@",x);
}];
// 4.發(fā)送
[subject sendNext:@"發(fā)送原始數(shù)據(jù)"];
其他場景:
順序組合 : concat 比較類似于串行隊列
返回最后的信號 : then?
壓縮信號 : zip 只有當多個信號都有發(fā)送數(shù)據(jù)時才會調(diào)用
組合 : combineLatest 同時監(jiān)聽多個信號
合并 : merge 任一信號發(fā)送數(shù)據(jù)就會執(zhí)行,類似并行隊列
這里就不上代碼了热康,只需要知道有這些個類型,及用法劣领,到時候根據(jù)需要自行百度就好姐军。
最后,就如何結(jié)合MVVM實際用法,簡單談下方法奕锌,由于C層只要求展示UI和用戶交互外著觉,可以處理非常簡單的邏輯外,其余的事情我們直接交給ViewModel層來處理惊暴,可以在ViewModel里面設置各種信號屬性饼丘,同時讓C層持有ViewModel作為屬性,在事件需要處理時辽话,使用RACComand或者RACSubject或者RACSignal來將事件轉(zhuǎn)化成信號肄鸽。
另外需要特別主要的是:
1.輸入框的信號(比如:讓ModelView的屬性變化通過RAC宏來綁定C層的輸入框的信號)
2.RAC宏的優(yōu)越性