UITableView优化
作为iOS开发,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻。
关于TableView,我想最核心的就是UITableViewCell的重用机制了。
简单来说呢就是当TableView滚动时,会调tableView:cellForRowAtIndexPath:这个方法,TableView只会创建屏幕内或者只比屏幕多一点点的cell,当滚动需要展现新的cell的时候,TableView首先会把已经移出屏幕外的cell放入到缓存池中去,然后再从缓存池中取出新的cell用来展示,当缓存池中没有的时候,则会创建新的cell。但是cell可能不仅仅是一种,我们怎么来辨别我们需要的cell呢?苹果公司已经为我们做好了一切,我们只需要简单地设置一个identifier即可,TableView便可自动根据identifier从缓存池中去出相应cell出来复用。这样就极大的节省了内存的开销。
知道cell的复用原理后,我们再来看看TableView的回调方法。我们知道,TableView继承自UIScrollView,必须先确定它的contentSize和每个cell的位置,这样才能正确的放置每个cell。所以在创建或者复用cell之前,tableView会调用tableView:heightForRowAtIndexPath:来确定contentSize和每个cell的高度,之后再调用tableView:cellForRowAtIndexPath:显示相应的cell。然而此举对于那些成百上千不定高的cell,计算高度会相当消耗性能。
所以首先我们围绕cell来看看TableView如何进行优化。
1.cell复用
这个很简单,只要注册一下,便会自动复用
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *Identifier = @"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ID];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:ID];
} return cell;
}
这里说一句,有很多人会在这里给cell进行赋值操作,绑定数据,但是最近看了一篇文章https://medium.com/ios-os-x-development/perfect-smooth-scrolling-in-uitableviews-fd609d5275a5#.373u9fh4p,里面说到不要在这个方法中进行数据绑定,因为TableView会为每个cell调用一次这个方法,它应该快速执行,我们应该快速的返回cell重用实例。我们可以在tableView:willDisplayCell:forRowAtIndexPath:这个方法中进行数据绑定。
2.cell的高度计算
这边我们分为两种cell,一种是定高的cell,另外一种是动态高度的cell
a.定高的cell,应该采用如下方式:
self.tableView.rowHeight = 88;
这个方法指定了所有cell高度都是88的tableview,rowHeight默认的值是44,所以一个空的TableView会显示成这个样子。对于定高cell,直接采用上面方式给定高度,不需要实现tableView:heightForRowAtIndexPath:以节省不必要的计算和开销。
b.动态高度的cell
我们需要实现它的代理,来给出高度:
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
// return xxx
}
这个方法给出后,上面的rowHeight的设置将会变成无效。在这个方法中,我们需要提高cell高度的计算效率,来节省时间。
需要说明的是自从iOS8之后有了self-sizing cell的概念,cell可以自己算出高度,但目前市面上的公司最低支持iOS8,能用上这个方法可能还有好久。
除了提高cell高度的计算效率之外,对于已经计算出的高度,我们需要进行缓存,对于已经计算过的高度,没有必要进行计算第二次。
此外,具体对于如何优化cell高度计算,何时缓存cell高度,这篇博客给出了非常好的说明,强烈推荐有兴趣的深读一下。http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/
3.渲染
为了保证TableView的流畅,当快速滑动的时候,cell必须被快速的渲染出来。所以cell渲染的速度必须快。如何提高cell的渲染速度呢?
a.当有图像时,预渲染图像,在bitmap context先将其画一遍,导出成UIImage对象,然后再绘制到屏幕,这会大大提高渲染速度。具体做法可以参考:《利用预渲染加速显示iOS图像》
b.渲染最好时的操作之一就是混合(blending)了,所以我们不要使用透明背景,将cell的opaque值设为Yes,背景色不要使用clearColor,尽量不要使用阴影渐变等
c.由于混合操作是使用GPU来执行,我们可以用CPU来渲染,这样混合操作就不再执行。可以在UIView的drawRect方法中自定义绘制,具体可参考:http://southpeak.github.io/blog/2015/12/20/perfect-smooth-scrolling-in-uitableviews/
4.减少视图的数目
我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。
5.减少多余的绘制工作
在实现drawRect方法的时候,它的参数rect就是我们需要绘制的区域,在rect范围之外的区域我们不需要进行绘制,否则会消耗相当大的资源
6.不要给cell动态添加subView
在初始化cell的时候就添加好,然后根据需要来设置hide属性显示和隐藏
7.异步化UI,不要阻塞主线程
我们时常会看到这样一个现象,就是加载时整个页面卡住不动,怎么点都没用,仿佛死机了一般。原因是主线程被阻塞了。所以对于网路数据的请求或者图片的加载,我们可以开启多线程,异步话操作
8.滑动时按需加载对应的内容
//按需加载 - 如果目标行与当前行相差超过指定行数,只在目标滚动范围的前后指定3行加载。
- (void)scrollViewWillEndDragging:(UIScrollView *)scrollView withVelocity:(CGPoint)velocity targetContentOffset:(inout CGPoint *)targetContentOffset{
NSIndexPath *ip = [self indexPathForRowAtPoint:CGPointMake(, targetContentOffset->y)];
NSIndexPath *cip = [[self indexPathsForVisibleRows] firstObject];
NSInteger skipCount = ;
if (labs(cip.row-ip.row)>skipCount) {
NSArray *temp = [self indexPathsForRowsInRect:CGRectMake(, targetContentOffset->y, self.width, self.height)];
NSMutableArray *arr = [NSMutableArray arrayWithArray:temp];
if (velocity.y<) {
NSIndexPath *indexPath = [temp lastObject];
if (indexPath.row+) {
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row- inSection:]];
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row- inSection:]];
[arr addObject:[NSIndexPath indexPathForRow:indexPath.row- inSection:]];
}
}
[needLoadArr addObjectsFromArray:arr];
}
}
记得在tableView:cellForRowAtIndexPath:方法中加入判断:
if (needLoadArr.count>&&[needLoadArr indexOfObject:indexPath]==NSNotFound) {
[cell clear];
return;
}
滑动很快时,只加载目标范围内的cell,这样按需加载(配合SDWebImage),极大提高流畅度。
最后,对于TableView的优化还有很多方面没有提及,希望大家多多交流~
参考文章
http://blog.sunnyxx.com/2015/05/17/cell-height-calculation/
http://southpeak.github.io/blog/2015/12/20/perfect-smooth-scrolling-in-uitableviews/
UITableView优化的更多相关文章
- UITableView优化技巧
UITableView的简单认识 UITableView最核心的思想就是UITableViewCell的重用机制.简单的理解就是:UITableView只会创建一屏幕(或一屏幕多一点)的UITable ...
- UITableView优化那点事
forkingdog关于UITableView优化的框架其实已经能够应用在一般的场景,且有蛮多的知识点供我们借鉴,借此站在巨人的肩膀上来分析一把. 至于UITableView的瓶颈在哪里,我相信网上随 ...
- [转] 详细整理:UITableView优化技巧
原文:http://www.cocoachina.com/ios/20150602/11968.html 最近在微博上看到一个很好的开源项目VVeboTableViewDemo,是关于如何优化 ...
- uitableview 优化
1. http://www.cocoachina.com/ios/20150602/11968.html 最近在微博上看到一个很好的开源项目VVeboTableViewDemo,是关于如何优化UITa ...
- UITableView优化方案
1.UITableView的简单认识 > UITableView最核心的思想就是UITableViewCell的重用机制.简单的理解就是:UITableView只会创建一屏幕(或一屏幕多一点)的 ...
- UITableView 优化总结
最近在微博上看到一个很好的开源项目VVeboTableViewDemo,是关于如何优化UITableView的.加上正好最近也在优化项目中的类似朋友圈功能这块,思考了很多关于UITableView的优 ...
- iOS UITableView优化
一.Cell 复用 在可见的页面会重复绘制页面,每次刷新显示都会去创建新的 Cell,非常耗费性能. 解决方案:创建一个静态变量 reuseID,防止重复创建(提高性能),使用系统的缓存池功能. s ...
- UITableView优化的那些事儿
作为iOS开发,UITableView可能是平时我们打交道最多的UI控件之一,其重要性不言而喻. 关于TableView,我想最核心的就是UITableViewCell的重用机制了. 简单来说呢就是当 ...
- UITableview优化随笔(1)-提高加载更多内容时的效率
UITableView上拉加载更多的功能相信很多应用都会用到,类似朋友圈.微博这样的应用,tableView中的数据内容高度根据内容来变化,同时需要加载大量的数据(上拉加载更多),要怎样才能保证加载数 ...
随机推荐
- JS原生第五篇 (帅哥)
1.1 节点 1. 节点 网页是有很多的节点组成的 . 元素节点 指的是 : 标签 li span 文本节点 属性节点 父子兄弟 父 parent ...
- SSISDB8:使用SSISDB记录的消息Troubleshoot packages
在执行Package时,SSISDB都会创建唯一的OperationID 和 ExecutionID,标识对package执行的操作和执行实例(Execution Instance),并记录opera ...
- SSISDB1:使用SSISDB管理SSIS Projects
使用Project Deployment Model,将SSIS Project部署到Integration Services Catalog之后,SSISDB负责管理SSIS Project.在SS ...
- 小谈MVC 模式
MVC (Modal View Controler) 本来是存在于Desktop程序中的,M是指数据模型,V是指用户界面,C则是控制器.使用MVC的目的是将M和V的实现代码分离,从而使同一个程序可以使 ...
- 在浏览器中输入URL按下回车键后发生了什么
在浏览器中输入URL按下回车键后发生了什么 [1]解析URL[2]DNS查询,解析域名,将域名解析为IP地址[3]ARP广播,根据IP地址来解析MAC地址[4]分别从应用层到传输层.网络层和数据链路层 ...
- 应用程序框架实战三十:表现层及ASP.NET MVC介绍(一)
本文将介绍表现层及ASP.NET MVC的一些要点,特别是ASP.NET MVC的一些抽象和封装技巧,如果你对MVC还不了解,可以参考<ASP.NET MVC4 高级编程>,作者Jon G ...
- Oracle_多表查询
SQL多表查询 等值和不等值连接查询 从多个表中获取数据:如果在查询的时候,直接从多个表中获取数据.没有添加条件判断,会出现"笛卡尔积"错误 笛卡尔积错误 笛卡尔集会在下面条件下产 ...
- BAT及各大互联网公司2014前端笔试面试题--JavaScript篇
很多面试题是我自己面试BAT亲身经历碰到的.整理分享出来希望更多的前端er共同进步吧,不仅适用于求职者,对于巩固复习js更是大有裨益. 而更多的题目是我一路以来收集的,也有往年的,答案不确保一定正确, ...
- Cesium应用篇:3控件(3)SelectionIndicator& InfoBox
假设这样一个场景,用户在Cesium球上加载了一个GeoJson文件(DataSource),里面是全美国所有州的Geometry信息(Entity),叠加到球面后,你自然会有一种冲动,点击某一个州, ...
- C#缓存操作
1.缓存辅助方法类的接口代码: public interface IThrottleStore { /// <summary> /// 试图获取值 /// </summary> ...