你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 控制器瘦身及tableView相關

控制器瘦身及tableView相關

編輯:IOS開發綜合

一、關於MVVM設計模式

網上的介紹很多,簡單說下我的理解。

個人理解:

MVVM = 控制器 + 視圖 + 數據模型 + 視圖模型

其中 視圖模型View - Model 是將 控制控制器中的 網絡請求 下拉刷新 下拉加載 及用戶交互操作 剝離出來 放到一個工具類裡面 由此達到解耦合為控制器瘦身的目的。
 

二、關於小型工廠模式的使用

開發過程中UITableView的使用頻率很高,可你是怎樣創建tableView的呢?UITableViewController是一個不錯的選擇,自帶一個tableView 而且你需要做的只是實現它的協議方法就可以了。省去了創建tableView 簽代理的麻煩,而且UITableViewController繼承於UIViewController 所以跟你在UIViewController上創建tableView沒區別。

此時問題來了,當你的tableView的cell有多種的時候怎麼辦?肯定是在返回cell的協議方法裡面進行判斷了。可是這樣你不會覺得看著很亂麼?而且返回行高的時候也需要判斷,這就不可避免增加控制器的代碼量,而且返回cell的類型明顯不是控制器的責任,控制器只是起協調作用的。這時我們就想可不可以把cell的返回類型 返回行高抽出一個類來實現呢?通過傳入一些參數 直接返回對應的行高 cell類型。答案是肯定的。

上面所說ViewModel則可以實現網絡請求 用戶交互 等業務邏輯 只需傳入對應的參數就好。

效果如下:

 

\
返回cell
\
cell點擊方法
\
下拉刷新及上拉加載

// Demo用到的API為新浪新聞 ,一共三種cell。

三、具體實現

實踐出真知,通過一個簡單的例子感受下。

新建類:

1.網絡請求類:JWNetTool,簡單對AFN做一個封裝

\
網絡請求類

2.數據模型:JWModel

創建一些用得到的屬性,封裝初始化方法,重寫 -(void)setValue:(id)value forUndefinedKey:(NSString *)key

3.ViewModel

\
業務邏輯

4.cell工廠

\
cell工廠接口

內部實現

#import "JWCellFactory.h"

#import "JWModel.h"

@implementation JWCellFactory

+ (UITableViewCell *)creatTableViewCellWithModel:(JWModel *)model TableView:(UITableView *)tableView IndexPath:(NSIndexPath *)indexPath

{

return [self creatTableViewCellWithModel:model TableView:tableView IndexPath:indexPath CellType:[self cellTypeWithModel:model]];

}

+ (UITableViewCell *)creatTableViewCellWithModel:(JWModel *)model TableView:(UITableView *)tableView IndexPath:(NSIndexPath *)indexPath CellType:(CellType)type

{

UITableViewCell *cell = nil;

switch (type) {

case 1:

cell = [tableView dequeueReusableCellWithIdentifier:@"JWOnePictureCell"];

tableView.rowHeight = 120;

break;

case 0:

cell = [tableView dequeueReusableCellWithIdentifier:@"JWBigPictureCell"];

cell.backgroundColor = [UIColor yellowColor];

tableView.rowHeight = 150;

break;

case 2:

cell = [tableView dequeueReusableCellWithIdentifier:@"JWThreePicsCell"];

cell.backgroundColor = [UIColor greenColor];

tableView.rowHeight = 180;

break;

default:

break;

}

return cell;

}

+(CellType)cellTypeWithModel:(JWModel *)model

{

if (![model.category isEqualToString:@"hdpic"]) {

if ([model.category isEqualToString:@"cms"]) {

return NewsOneImageCell;

}else{

return NewsOneBigImageCell;

}

}

return NewsThreeImageCell;

}

@end

5.接下來我們看下控制器裡的代碼:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

return 1;

}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

return self.models.count;

}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

return [JWCellFactory creatTableViewCellWithModel:self.models[indexPath.row] TableView:tableView IndexPath:indexPath];

}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath

{

[JWViewModel cellSeletedActionWithTableView:tableView IndexPath:indexPath ViewController:self Arr:self.models];

}

再看下數據請求相關代碼:

self.tableView.mj_header = [MJRefreshNormalHeader headerWithRefreshingBlock:^{

[JWViewModel getDataWithUrl:URL TableView:self.tableView ViewController:self];

}];

[self.tableView.mj_header beginRefreshing];

#pragma mark - 下拉加載的實現

self.tableView.mj_footer = [MJRefreshAutoStateFooter footerWithRefreshingBlock:^{

[JWViewModel getMoreDataWithUrl:MORE TableView:self.tableView ViewController:self Models:self.models];

}];

6.看下注冊cell方法

[self.tableView registerNib:[UINib nibWithNibName:@"JWOnePictureCell" bundle:nil] forCellReuseIdentifier:@"JWOnePictureCell"];

[self.tableView registerNib:[UINib nibWithNibName:@"JWBigPictureCell" bundle:nil] forCellReuseIdentifier:@"JWBigPictureCell"];

[self.tableView registerNib:[UINib nibWithNibName:@"JWThreePicsCell" bundle:nil] forCellReuseIdentifier:@"JWThreePicsCell"];

看到這裡瘦身該做的已經差不多了接下來談談tableView一些可以優化的地方

四、UITableView相關優化

1.行高固定用屬性賦值:

能不用協議方法就不用協議方法,如果行高確定則通過self.tableView.rowHeight = 100;來賦值

因為協議方法的話會在初始化的時候走很多次 , 假設當前數組有20條數據

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 這個方法會走60次 而且每當一個cell出現的時候都會再走一次這個方法。多次走這個方法主要是動態獲取當前tableView的contentSize這一屬性。

所以行高確定的話 屬性賦值會節省一定的資源

2.行高非固定的話 -> 可以采用緩存機制 將已有行高緩存到字典 下次用的時候可以直接取出 不必再重新計算

3.行高動態變化 但變化幅度不是很大 那麼就可以采用估算的方法了.假如行高在120 左右變化 且幅度不是很大 的話 self.tableView.estimatedRowHeight = 120;- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath

再結合協議方法緩存行高達到優化作用。

4.刷新方法

insertRowsAtIndexPaths:<#(nonnull NSArray*)#> withRowAnimation:<#(UITableViewRowAnimation)#>

與 reloaData


試想一下 如果我現在已經有1000行cell了,而且都是行高都是動態的那麼我再獲取20行cell 之後reloaData 那麼可以想象了 從第0行一直刷新到第1019行 ,這是很浪費資源的.所以可以采用insert方法去更新cell

Demo中ViewModel上拉加載方法裡有用到:

for (NSDictionary *temp in list) {

JWNewsModel *model = [JWNewsModel modelWithDic:temp];

[arr addObject:model];

vc.dataArr = arr;

[tableView insertRowsAtIndexPaths:@[[NSIndexPath indexPathForItem:arr.count - 1 inSection:0]] withRowAnimation:UITableViewRowAnimationNone];

}

5.異步繪制cell 有興趣的可以去查一下

6.cell盡量手動創建 盡量少用Xib畢竟 加載時轉化成代碼也會消耗一定的時間

7.cell盡量不那麼復雜 圖層盡量少 畢竟cell復雜 繪制的話會消耗更多的時間

8.按需加載cell如果我現在飛快的滑動tableView的話 是不是中間有幾個cell沒必要立馬創建出來 而是首先創建屏幕將要顯示的cell?

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved