減少比例= (360(原來的行數)-159(瘦身後的行數))/360 = 56%
父類 MVC 和MVVM 前後基本不動
父類主要完成如下三個功能:
- 1)功能:MJRefrsh +上拉下拉沒有更多資料,封裝到父類的控制器 子類呼叫3行程式碼增加所有重新整理功能
- 2)網路失敗:顯示網路錯誤的連結,寫在父類子類呼叫一行程式碼就可
- 3)載入資料完成,列表中沒有資料提示View,比如購買介面,沒有購 買記錄,寫在父類子類一行程式碼呼叫
瘦身思路(總的程式碼量增加了30多行,但是控制器更清爽了)
- 網路前網路請求函式是這樣的
瘦身結果
瘦身具體實現
1)網路請求移到ViewModel
以前網路程式碼直接寫在控制器中,如下所示
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
- (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封裝後控制器中的網路請求是這樣的,控制器只取需要的東西,如下所示,不關心一些無關的細節,細節移到ViewModel中,5行搞定了網路請求獲取網路資料,還算精簡吧!
1 2 3 4 5 |
- (void)loadDataForCaseDeatailMsg:(NSString*)caseManageId{ [QTCaseDetailViewModel caseDetailhudView:self.view caseManageId:caseManageId getDataSuccess:^(id item, NSInteger totalPage) { [self gotoChatViewController:item]; } getDataFailure:^(NSError *error) {}]; } |
— 具體實現在viewModle中,viewModel新增hud,完成字典轉模型,對後臺做錯誤處理,顯示錯誤(部分工作在我自己封裝的底層網路請求實現的)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
+ (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中,本控制器有三個網路請求 這樣節省程式碼量很可觀
2) datasource,以前直接寫在控制機器中,現在寫到dataSource 檔案中,控制器中呼叫dataSource這個類
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
/* 本類作用:用以處理TableView以及CollectionView的資料來源 */ #import @import UIKit; // 用於配置當前Cell的資料 // id cell表示什麼型別的Cell // id item表示什麼型別的模型物件 typedef void (^TableViewCellConfigureBlock)(id cell, id item); @interface QTArrayDataSource : NSObject // 引數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 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 |
#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程式碼中, 以協議的方式載入資料來源
1 2 3 4 5 6 7 8 9 10 11 12 |
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行左右,代理剝離有點麻煩,感覺沒有必要
- 建立collectionView 的程式碼沒剝離,剝離出來可以再減少20行左右,也參考一些別人的文章,目前覺得就這樣了,沒必要的
- 也參考了一些別人的程式碼原文連結
如何正確的寫好一個UITableView,寫的也很高大上,感覺各種繼承,真的很複雜耶
- 程式碼 不能過度封裝,也不能不封裝
有人對我的網路請求比較感興趣,我的網路請求,針對公司的後臺資料結構做了封裝,hud 也封裝到網路請求中了
- 作者開發經驗總結的文章推薦,持續更新學習心得筆記
Runtime 10種用法(沒有比這更全的了)
成為iOS頂尖高手,你必須來這裡(這裡有最好的開源專案和文章)
iOS逆向Reveal檢視任意app 的介面
JSPatch (實時修復App Store bug)學習(一)
iOS 高階工程師是怎麼進階的(補充版20+點)
擴大按鈕(UIButton)點選範圍(隨意方向擴充套件哦)
最簡單的免證書真機除錯(原創)
通過分析微信app,學學如何使用@2x,@3x圖片
TableView之MVVM與MVC之對比
使用MVVM減少控制器程式碼實戰(減少56%)
ReactiveCocoa新增cocoapods 配置圖文教程及坑總結