使用MVVM減少控制器代碼實戰(zhàn)(減少56%)

減少比例= (360(原來的行數)-159(瘦身后的行數))/360 = 56%

父類 MVC 和MVVM 前后基本不動

父類主要完成如下三個功能:

  • 1)功能:MJRefrsh +上拉下拉沒有更多數據,封裝到父類的控制器 子類調用3行代碼增加所有刷新功能
  • 2)網絡失敗:顯示網絡錯誤的鏈接,寫在父類子類調用一行代碼就可
  • 3)加載數據完成,列表中沒有數據提示View,比如購買界面,沒有購 買記錄,寫在父類子類一行代碼調用

瘦身思路(總的代碼量增加了30多行,但是控制器更清爽了)

  • 網絡前網絡請求函數是這樣的

瘦身結果

瘦身具體實現(xiàn)

1)網絡請求移到ViewModel

以前網絡代碼直接寫在控制器中,如下所示
- (void)loadDataForCaseDeatailMsg:(NSString*)caseManageId{
    NSMutableDictionary *dict = createMutDict;
    [dict setObject:@"case-info" forKey:@"method"];
    [dict setObject:caseManageId forKey:@"caseManageId"];
    [QTFHttpTool    requestPara:dict
                        needHud:YES
                        hudView:self.view
                 loadingHudText:nil
                   errorHudText:nil
                         sucess:^(NSDictionary *json) {
                             BOOL success = (BOOL)[json[@"success"] boolValue];
                             if(success){
                                 QTCaseDetailModel *caseDetailModel = [[QTCaseDetailModel alloc]init];
                                 caseDetailModel.expertId = json[@"expertId"];
                                 caseDetailModel.userName = json[@"userName"];
                                 caseDetailModel.data = [QTCaseDetailMsgModel objectArrayWithKeyValuesArray:json[@"data"]];
                                 [self gotoChatViewController:caseDetailModel];
                                 
                             }
                         }failur:^(NSError *error) {
                             
                         }];
}
  • MVVM封裝后控制器中的網絡請求是這樣的,控制器只取需要的東西,如下所示,不關心一些無關的細節(jié),細節(jié)移到ViewModel中,5行搞定了網絡請求獲取網絡數據,還算精簡吧!
- (void)loadDataForCaseDeatailMsg:(NSString*)caseManageId{
    [QTCaseDetailViewModel caseDetailhudView:self.view caseManageId:caseManageId getDataSuccess:^(id item, NSInteger totalPage) {
        [self gotoChatViewController:item];
    } getDataFailure:^(NSError *error) {}];
}

-- 具體實現(xiàn)在viewModle中,viewModel添加hud,完成字典轉模型,對后臺做錯誤處理,顯示錯誤(部分工作在我自己封裝的底層網絡請求實現(xiàn)的)

+ (void)caseDetailhudView:(UIView*)hudView caseManageId:(NSString*)caseManageId getDataSuccess:(GetDataAllSuccessBlock)success getDataFailure:(GetDataFailureBlock)failure{
    NSMutableDictionary *dict = createMutDict;
    [dict setObject:@"case-info" forKey:@"method"];
    [dict setObject:caseManageId forKey:@"caseManageId"];
    [QTFHttpTool    requestPara:dict
                        needHud:YES
                        hudView:hudView
                 loadingHudText:nil
                   errorHudText:nil
                         sucess:^(NSDictionary *json) {
                             BOOL success1 = (BOOL)[json[@"success"] boolValue];
                             if(success1){
                                 QTCaseDetailModel *caseDetailModel = [[QTCaseDetailModel alloc]init];
                                 caseDetailModel.expertId = json[@"expertId"];
                                 caseDetailModel.userName = json[@"userName"];
                                 caseDetailModel.data = [QTCaseDetailMsgModel objectArrayWithKeyValuesArray:json[@"data"]];
                                 success(caseDetailModel,1);
                             }
                         }failur:^(NSError *error) {
                             
                         }];

}

  • 將網絡請求部分工作移到Viewmodel中,本控制器有三個網絡請求 這樣節(jié)省代碼量很可觀

2) datasource,以前直接寫在控制機器中,現(xiàn)在寫到dataSource 文件中,控制器中調用dataSource這個類

/*
 本類作用:用以處理TableView以及CollectionView的數據源
 */

#import <Foundation/Foundation.h>
@import UIKit;

// 用于配置當前Cell的數據
// id cell表示什么類型的Cell
// id item表示什么類型的模型對象
typedef void (^TableViewCellConfigureBlock)(id cell, id item);

@interface QTArrayDataSource : NSObject <UITableViewDataSource, UICollectionViewDataSource>

// 參數1:用以數據源的控制瞳别,主要是通過改數組來控制當前tableView或者collectionView顯示Cell的數量
// 參數2:當前需要顯示的cell的重用標示
// 參數3:用以配置當前cell數據的block
- (id)initWithItems:(NSArray *)anItems
     cellIdentifier:(NSString *)aCellIdentifier
 configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock;

// 通過indexPath來獲取當前具體的某一個對象
- (id)itemAtIndexPath:(NSIndexPath *)indexPath;

@end

#import "QTArrayDataSource.h"
#import "QTSpecialCaseCell.h"

@interface QTArrayDataSource ()

// 當前數據數組
@property (nonatomic, strong) NSArray *items;
// 當前cell重用標示
@property (nonatomic, copy) NSString *cellIdentifier;
// 當前配置cell的block
@property (nonatomic, copy) TableViewCellConfigureBlock configureCellBlock;

@end


@implementation QTArrayDataSource

- (id)init
{
    return nil;
}

- (id)initWithItems:(NSArray *)anItems
     cellIdentifier:(NSString *)aCellIdentifier
 configureCellBlock:(TableViewCellConfigureBlock)aConfigureCellBlock
{
    self = [super init];
    if (self) {
        _items = anItems;
        _cellIdentifier = aCellIdentifier;
        _configureCellBlock = [aConfigureCellBlock copy];
    }
    return self;
}

- (id)itemAtIndexPath:(NSIndexPath *)indexPath
{
    return self.items[(NSUInteger)indexPath.row];
}


#pragma mark UITableViewDataSource

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return self.items.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:self.cellIdentifier
                                                            forIndexPath:indexPath];
    // 獲取當前某一行的對象
    id item = [self itemAtIndexPath:indexPath];
    // 通過調用該block配置當前cell顯示的內容
    self.configureCellBlock(cell, item);
    return cell;
}


#pragma mark UICollectionDataSource

- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
    return self.items.count;
}

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
    QTSpecialCaseCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:self.cellIdentifier
                                                                           forIndexPath:indexPath];
    
    // 獲取當前某一行的對象
    
    id item = [self itemAtIndexPath:indexPath];
    // 通過調用該block配置當前cell顯示的內容
    self.configureCellBlock(cell, item);
    return cell;
}



@end

3) viewdidload代碼中, 以協(xié)議的方式加載數據源

  TableViewCellConfigureBlock configureCell = ^(QTSpecialCaseCell
                                            *cell, id data) {
        [cell configureForCell:data];
    };
    [_collectionView registerClass:[QTSpecialCaseCell class] forCellWithReuseIdentifier:CellIdentify];
    self.arrayDataSource = [[QTArrayDataSource alloc]
                            initWithItems:self.data
                            cellIdentifier:CellIdentify
                            configureCellBlock:configureCell];
    self.collectionView.dataSource = self.arrayDataSource;
    self.collectionView.delegate = self;
    [self refreshOneCreateCollectionView:_collectionView methodSelStr:@"loadData"];

4) 本文的待討論的部分

  • 代理方法沒有剝離出來,如果剝離出來,控制器進一步減少到120行左右,代理剝離有點麻煩,感覺沒有必要

  • 創(chuàng)建collectionView 的代碼沒剝離,剝離出來可以再減少20行左右,也參考一些別人的文章,目前覺得就這樣了,沒必要的

  • 也參考了一些別人的代碼原文鏈接
    如何正確的寫好一個UITableView,寫的也很高大上,感覺各種繼承,真的很復雜耶

Snip20160708_9.png
  • 代碼 不能過度封裝,也不能不封裝

有人對我的網絡請求比較感興趣,我的網絡請求,針對公司的后臺數據結構做了封裝,hud 也封裝到網絡請求中了


最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
  • 序言:七十年代末裙犹,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子稀颁,更是在濱河造成了極大的恐慌表锻,老刑警劉巖,帶你破解...
    沈念sama閱讀 219,366評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件们衙,死亡現(xiàn)場離奇詭異,居然都是意外死亡碱呼,警方通過查閱死者的電腦和手機蒙挑,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,521評論 3 395
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來愚臀,“玉大人忆蚀,你說我怎么就攤上這事」昧眩” “怎么了馋袜?”我有些...
    開封第一講書人閱讀 165,689評論 0 356
  • 文/不壞的土叔 我叫張陵,是天一觀的道長炭分。 經常有香客問我桃焕,道長剑肯,這世上最難降的妖魔是什么捧毛? 我笑而不...
    開封第一講書人閱讀 58,925評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上呀忧,老公的妹妹穿的比我還像新娘师痕。我一直安慰自己,他們只是感情好而账,可當我...
    茶點故事閱讀 67,942評論 6 392
  • 文/花漫 我一把揭開白布胰坟。 她就那樣靜靜地躺著,像睡著了一般泞辐。 火紅的嫁衣襯著肌膚如雪笔横。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,727評論 1 305
  • 那天咐吼,我揣著相機與錄音吹缔,去河邊找鬼。 笑死锯茄,一個胖子當著我的面吹牛厢塘,可吹牛的內容都是我干的。 我是一名探鬼主播肌幽,決...
    沈念sama閱讀 40,447評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼晚碾,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了喂急?” 一聲冷哼從身側響起格嘁,我...
    開封第一講書人閱讀 39,349評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎煮岁,沒想到半個月后讥蔽,有當地人在樹林里發(fā)現(xiàn)了一具尸體,經...
    沈念sama閱讀 45,820評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡画机,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 37,990評論 3 337
  • 正文 我和宋清朗相戀三年冶伞,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片步氏。...
    茶點故事閱讀 40,127評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡响禽,死狀恐怖,靈堂內的尸體忽然破棺而出荚醒,到底是詐尸還是另有隱情芋类,我是刑警寧澤,帶...
    沈念sama閱讀 35,812評論 5 346
  • 正文 年R本政府宣布界阁,位于F島的核電站侯繁,受9級特大地震影響,放射性物質發(fā)生泄漏泡躯。R本人自食惡果不足惜贮竟,卻給世界環(huán)境...
    茶點故事閱讀 41,471評論 3 331
  • 文/蒙蒙 一丽焊、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧咕别,春花似錦技健、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,017評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至偿短,卻和暖如春欣孤,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背昔逗。 一陣腳步聲響...
    開封第一講書人閱讀 33,142評論 1 272
  • 我被黑心中介騙來泰國打工导街, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人纤子。 一個月前我還...
    沈念sama閱讀 48,388評論 3 373
  • 正文 我出身青樓搬瑰,卻偏偏與公主長得像,于是被迫代替她去往敵國和親控硼。 傳聞我的和親對象是個殘疾皇子泽论,可洞房花燭夜當晚...
    茶點故事閱讀 45,066評論 2 355

推薦閱讀更多精彩內容