1. cell重用,注册重用标识符
tableView会根据屏幕可显示的cell个数去创建cell,当cell划出屏幕时会放到重用池,有cell需要显示时,会根据标识符先去重用池取,有则拿出来显示,没有再去创建。
-
static NSString *identifier = @"cellIdentifier";
-
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
-
if (!cell) {
-
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
-
}
-
return cell;
2. 避免cell的重新布局
cell的布局填充等操作比较耗时,一般创建时就布局好,如可以将cell单独放到一个自定义类,初始化时就布局好。
3. 提前计算并缓存cell的属性及内容
tableView实现数据源方法后,编译器会先调用tableView:heightForRowAtIndexPath:确定每一个cell的高度,在调用tableView:cellForRowAtIndexPath:创建要显示的cell,滚动时,每当cell进入屏幕都会计算高度,编译器知道高度后,会去创建cell,所以提前缓存cell高度可以避免重复的计算。如果cell是固定高度直接写self.tableView.rowHeight = 70;不需要实现tableView:heightForRowAtIndexPath:方法以节省不必要的开销。
举个例子来说:如果当前数据源有100条数据,当前屏幕最多只能显示5个。那么刷新UITableView时,UITableView会先调用100次tableView:heightForRowAtIndexPath:方法,然后调用5次tableView:cellForRowAtIndexPath:方法;滚动屏幕时,每当Cell进入屏幕,都会调用一次tableView:heightForRowAtIndexPath:、tableView:cellForRowAtIndexPath:方法。
所以尽量不要在tableView:heightForRowAtIndexPath:方法中调用tableView:cellForRowAtIndexPath:方法。
4. 减少cell中控件的数量
我们在cell上添加系统控件的时候,实际上系统都会调用底层的接口进行绘制,大量添加控件时,会消耗很大的资源并且也会影响渲染的性能。当使用默认的UITableViewCell并且在它的ContentView上面添加控件时会相当消耗性能。所以目前最佳的方法还是继承UITableViewCell,并重写drawRect方法。尽量使cell的布局大致相同,不同风格的cell可以使用不同的重用标识符。
5. 尽量不要用透明属性
cell的opaque值设为Yes,尽量不要使用控件透明属性,cell自身也是,透明度也避免设置为0,渲染耗时比较长。
6. 使用局部刷新
如果只是更新某组、某行的话,使用局部刷新。
7. 网络数据异步加载,不要阻塞主线程
如果Cell内的内容来自web,需要加载网络数据,下载图片,配合SDWebImage、YYWebImage等实现异步加载、缓存。不要在主线程做一些文件的I/O操作。
8. 不要动态给cell添加或删除控件
尽量不要给cell动态添加删除控件,初始化时添加控件,不适用的可以先隐藏。
9. 按需加载cell
cell滚动很快时,只加载范围内的cell,可以提高流畅度。
10. 不要实现无用的代理方法,tableView只遵守两个协议
11. 圆角优化(点击查看:iOS 控件设置圆角,避免离屏渲染)
在APP开发中,圆角图片还是经常出现的。如果一个界面中只有少量圆角图片或许对性能没有非常大的影响,但是当圆角图片比较多的时候就会对性能产生明显的影响,我们设置圆角一般通过如下方式:
-
view.layer.cornerRadius = 5.f;
-
view.layer.masksToBounds = YES;
这样处理的渲染机制是GPU在当前屏幕缓冲区外新开辟一个渲染缓冲区进行工作,也就是离屏渲染,这会给我们带来额外的性能损耗,如果这样的圆角操作达到一定数量,会触发缓冲区的频繁合并和上下文的的频繁切换,性能的代价会宏观地表现在用户体验上——掉帧,点击链接查看如何正确设置圆角。注意一点,单独设置view.layer.masksToBounds = YES;是不会发生离屏渲染的,上面说过尽量不要使用控件透明,如一个标签UILable,尽量用如下方法:
-
label.backgroundColor = [UIColor whiteColor];
-
label.layer.masksToBounds = YES;
给定一个背景色,然后设置layer的masksToBounds属性为YES,因为如果label的内容是中文,label实际渲染区域要大于label的size,最外层多了一个sublayer,如果不设置,label的边缘外层颜色仍然需要计算,增加了GPU的性能消耗。
12. 不要做多余的绘制工作
在实现drawRect:的时候,异步绘制,它的rect参数就是需要绘制的区域,这个区域之外的不需要进行绘制。绘制cell不建议使用UIView,建议使用CALayer,从形式来说,UIView的绘制是建立在CoreGraphic上的,使用的是CPU。CALayer使用的是Core Animation,CPU,GPU通吃,由系统决定使用哪个。View的绘制使用的是自下向上的一层一层的绘制,然后渲染。Layer处理的是Texure,利用GPU的Texture Cache和独立的浮点数计算单元加速纹理的处理。从事件的响应来说,UIView是CALayer的代理,layer本身并不能响应事件,因为layer是直接继承自NSObject,不具备处理事件的能力。而UIView是继承了UIResponder的,这也是事件转发的角度上说明,view要比单纯的layer复杂的多。在滑动的列表上,多层次的view再加上各种手势的处理势必导致帧数的下降。
13. 预渲染图像
当新的图像出现时,仍然会有短暂的停顿现象。解决的办法就是在bitmap context里先将其画一遍,导出成UIImage对象,然后再绘制到屏幕。
cell内容经常变动,不要开启光栅化,shouldRasterize,光栅化是将一个layer预先渲染成位图(bitmap),再加入到缓存中,因为tableViewCell的绘制非常频繁,内容在不断的变化,如果使用了光栅化,会造成大量的离屏渲染降低性能。
14. 使用正确的数据结构来存储数据
15. 尽可能重用开销比较大的对象
如NSDateFormatter 和 NSCalendar等对象初始化非常慢,我们可以把它加入类的属性当中,或者创建单例来使用。
16. 尽量减少计算的复杂度
在高分屏尽量用ceil、floor或round取整。不要出现1.3,10.333这样的小数。
17. 复杂界面建议纯代码
xib、storyboard虽然方便,但仍然需要系统自动转码,并且对于一些自定义的绘制也有局限性。
猜你喜欢:UITableView简介, UITableView实用练习, MVC与MVVM设计模式简介, 基于MVC模式练习UITabelView使用, 基于MVVM模式练习UITableView使用。