控制器瘦身及tableView相关

来源:互联网 发布:西门子plc伺服编程案例 编辑:程序博客网 时间:2024/06/06 19:51

今天简单介绍下为ViewController瘦身的一些想法,不足之处还请指出。

一、关于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?

以上就是我对tableView可以优化 及 控制器瘦身的一些想法 不足之处还请指正,有好的建议的话欢迎提出来O(∩_∩)O哈哈~。

Demo地址

0 0
原创粉丝点击