控制器瘦身及tableView相关
2016-04-26 16:02
218 查看
今天简单介绍下为ViewController瘦身的一些想法,不足之处还请指出。
一、关于MVVM设计模式
网上的介绍很多,简单说下我的理解。
个人理解:
MVVM = 控制器 + 视图 + 数据模型 + 视图模型
其中 视图模型View - Model 是将 控制控制器中的 网络请求 下拉刷新 下拉加载 及用户交互操作 剥离出来 放到一个工具类里面 由此达到解耦合为控制器瘦身的目的。
二、关于小型工厂模式的使用
开发过程中UITableView的使用频率很高,可你是怎样创建tableView的呢?UITableViewController是一个不错的选择,自带一个tableView 而且你需要做的只是实现它的协议方法就可以了。省去了创建tableView 签代理的麻烦,而且[b]UITableViewController继承于UIViewController 所以跟你在UIViewController上创建tableView没区别。[/b]
此时问题来了,当你的tableView的cell有多种的时候怎么办?肯定是在返回cell的协议方法里面进行判断了。可是这样你不会觉得看着很乱么?而且返回行高的时候也需要判断,这就不可避免增加控制器的代码量,而且返回cell的类型明显不是控制器的责任,控制器只是起协调作用的。这时我们就想可不可以把cell的返回类型 返回行高抽出一个类来实现呢?通过传入一些参数 直接返回对应的行高 cell类型。答案是肯定的。
上面所说ViewModel则可以实现网络请求 用户交互 等业务逻辑 只需传入对应的参数就好。
效果如下:
![](http://upload-images.jianshu.io/upload_images/1967881-94be5564bb603565.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
返回cell
![](http://upload-images.jianshu.io/upload_images/1967881-c01e7af7b7d83adf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
cell点击方法
![](http://upload-images.jianshu.io/upload_images/1967881-e281974dbe19472a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
下拉刷新及上拉加载
// Demo用到的API为新浪新闻 ,一共三种cell。
三、具体实现
实践出真知,通过一个简单的例子感受下。
新建类:
1.网络请求类:JWNetTool,简单对AFN做一个封装
![](http://upload-images.jianshu.io/upload_images/1967881-2263d85b0fa96449.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
网络请求类
2.数据模型:JWModel
创建一些用得到的属性,封装初始化方法,重写 -(void)setValue:(id)value forUndefinedKey:(NSString *)key
3.ViewModel
![](http://upload-images.jianshu.io/upload_images/1967881-0854ac7e270f4ddd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
业务逻辑
4.cell工厂
![](http://upload-images.jianshu.io/upload_images/1967881-810530fb77e8f6de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
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一些可以优化的地方
四、[b]UITableView相关优化[/b]
[b]1.行高固定用属性赋值:[/b]
[b]能不用协议方法就不用协议方法,如果行高确定则通过self.tableView.rowHeight = 100;来赋值[/b]
[b]因为协议方法的话会在初始化的时候走很多次 , 假设当前数组有20条数据[/b]
[b]- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 这个方法会走60次 而且每当一个cell出现的时候都会再走一次这个方法。多次走这个方法主要是动态获取当前tableView的contentSize这一属性。[/b]
所以行高确定的话 属性赋值会节省一定的资源
2.行高非固定的话 -> 可以采用缓存机制 将已有行高缓存到字典 下次用的时候可以直接取出 不必再重新计算
3.行高动态变化 但变化幅度不是很大 那么就可以采用估算的方法了.假如行高在120 左右变化 且幅度不是很大 的话 self.tableView.estimatedRowHeight = 120;[b][b]- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath[/b]
再结合协议方法缓存行高达到优化作用。[/b]
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地址
一、关于MVVM设计模式
网上的介绍很多,简单说下我的理解。
个人理解:
MVVM = 控制器 + 视图 + 数据模型 + 视图模型
其中 视图模型View - Model 是将 控制控制器中的 网络请求 下拉刷新 下拉加载 及用户交互操作 剥离出来 放到一个工具类里面 由此达到解耦合为控制器瘦身的目的。
二、关于小型工厂模式的使用
开发过程中UITableView的使用频率很高,可你是怎样创建tableView的呢?UITableViewController是一个不错的选择,自带一个tableView 而且你需要做的只是实现它的协议方法就可以了。省去了创建tableView 签代理的麻烦,而且[b]UITableViewController继承于UIViewController 所以跟你在UIViewController上创建tableView没区别。[/b]
此时问题来了,当你的tableView的cell有多种的时候怎么办?肯定是在返回cell的协议方法里面进行判断了。可是这样你不会觉得看着很乱么?而且返回行高的时候也需要判断,这就不可避免增加控制器的代码量,而且返回cell的类型明显不是控制器的责任,控制器只是起协调作用的。这时我们就想可不可以把cell的返回类型 返回行高抽出一个类来实现呢?通过传入一些参数 直接返回对应的行高 cell类型。答案是肯定的。
上面所说ViewModel则可以实现网络请求 用户交互 等业务逻辑 只需传入对应的参数就好。
效果如下:
![](http://upload-images.jianshu.io/upload_images/1967881-94be5564bb603565.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
返回cell
![](http://upload-images.jianshu.io/upload_images/1967881-c01e7af7b7d83adf.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
cell点击方法
![](http://upload-images.jianshu.io/upload_images/1967881-e281974dbe19472a.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
下拉刷新及上拉加载
// Demo用到的API为新浪新闻 ,一共三种cell。
三、具体实现
实践出真知,通过一个简单的例子感受下。
新建类:
1.网络请求类:JWNetTool,简单对AFN做一个封装
![](http://upload-images.jianshu.io/upload_images/1967881-2263d85b0fa96449.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
网络请求类
2.数据模型:JWModel
创建一些用得到的属性,封装初始化方法,重写 -(void)setValue:(id)value forUndefinedKey:(NSString *)key
3.ViewModel
![](http://upload-images.jianshu.io/upload_images/1967881-0854ac7e270f4ddd.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
业务逻辑
4.cell工厂
![](http://upload-images.jianshu.io/upload_images/1967881-810530fb77e8f6de.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/1240)
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一些可以优化的地方
四、[b]UITableView相关优化[/b]
[b]1.行高固定用属性赋值:[/b]
[b]能不用协议方法就不用协议方法,如果行高确定则通过self.tableView.rowHeight = 100;来赋值[/b]
[b]因为协议方法的话会在初始化的时候走很多次 , 假设当前数组有20条数据[/b]
[b]- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath 这个方法会走60次 而且每当一个cell出现的时候都会再走一次这个方法。多次走这个方法主要是动态获取当前tableView的contentSize这一属性。[/b]
所以行高确定的话 属性赋值会节省一定的资源
2.行高非固定的话 -> 可以采用缓存机制 将已有行高缓存到字典 下次用的时候可以直接取出 不必再重新计算
3.行高动态变化 但变化幅度不是很大 那么就可以采用估算的方法了.假如行高在120 左右变化 且幅度不是很大 的话 self.tableView.estimatedRowHeight = 120;[b][b]- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath[/b]
再结合协议方法缓存行高达到优化作用。[/b]
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地址
相关文章推荐
- httpd的简单配置(转)
- 动画:让一张图片通过按钮点击缩放到一定的角落(转载的)
- 关于ShapeDrawable应用的一些介绍(中)之Gradient
- [置顶] MYSQL 视图操作
- iOS开发--多线程编程(一)NSThread
- c++对内存的浅谈以及内存泄漏问题的探讨之三
- HDU-1232 畅通工程
- android中微信、朋友圈分享无回调的问题
- JAVA中super()作用:调用父类构造方法和构造方法链
- LACP Bond配置(by quqi99)
- ONOS源码笔记--机制
- 如何说孩子才会听,怎么听孩子才肯说
- httpclient超时总结(转)
- CentOS 6.4编译安装和部署Zabbix 2.0版本监控(中文)
- 从CMO到龙泉寺弟子:佛法改变人生
- HTML5+Canvas+CSS3实现齐天大圣孙悟空腾云驾雾效果
- jquery checkbox勾选/取消勾选的诡异问题
- [工作点滴]新建分支 git 命令
- 文通车牌识别一体机的优势
- Android 加载图片时根据哪个类获得的值,大致判断什么时候Out Of Memory