UITableView表格性能优化(一)

作为一名iOS开发程序员,你肯定能写出TableView..但是这个TableView的性能到底怎么样呢...那就那就仁者见仁智者见智了..
网上的文章一抄一大把.在这里作为一个彩笔的我...也给几条建议吧...

1.cornerRadius

imageView.layer.cornerRadius = 10;
imageView.clipsToBounds = YES;

相信小伙伴们对cornerRaius并不陌生,如果在iOS8之前,在表格视图中如果频繁大量使用cornerRaius,就可能会对表格的性能产生影响...

UITableView表格性能优化(一)_第1张图片
15060063301952.jpg
UITableView表格性能优化(一)_第2张图片
15060092904512.jpg

你会发现,视图中用了cornerRaius的部分是红色的...
可能单单这样一个视图没什么问题,但是如果在tableView中会怎么样...
在每个单元格中可能就会对性能产生一定的影响了...
为什么会影响呢?是因为苹果对裁切做了透明效果的处理,混合模式变红就是一个很好的说明,而这个alpha可能会对性能造成影响...
但是据说iOS8之后苹果对cornerRaius做了优化,理论上说对性能的影响降低了....
但是还是感觉很不爽啊....
所以咱们还是自己开启图形上下文自己画把....
自己动手丰衣足食....

// UIImage 分类方法
- (instancetype)jb_circleImage {
    // 开启图形上下文   opaque 一定要写YES 表示不透明
    UIGraphicsBeginImageContextWithOptions(self.size, YES, 0);
    // 范围
    CGRect rect = CGRectMake(0, 0, self.size.width, self.size.height);  
    // 填充颜色<这里的颜色就你来定拉~~>
    [[UIColor whiteColor] setFill];
    UIRectFill(rect);
    // 裁剪
    [[UIBezierPath bezierPathWithOvalInRect:rect] addClip];
    // 绘制图片到圆上面
    [self drawInRect:rect];
    // 获得图片
    UIImage *image = UIGraphicsGetImageFromCurrentImageContext();
    // 结束图形上下文
    UIGraphicsEndImageContext();
    return image;
}
UITableView表格性能优化(一)_第3张图片
15060090974778.jpg

亲爱的小伙伴,是不是看到绿色就舒服多了....
如果你说反正也这个颜色也不在头上我也没办法...
谁让它不是王宝绿呢...
上面那个分类方法我是用贝塞尔路径切的,如果用上下文切也是可以的,调用CGContextClip(context)这个小函数,不过要多获取一下上下文~

2.缓存Cell的行高

各位小伙伴,如果你遇到Cell高度不同的时候是怎么处理的呢,相信老程序员们都还记得木有自动布局的那一段用frame计算行高的轻松的时刻....
而后来,我们有了AutoLayout,仅仅是因为苹果的机型变多了,从iPhone4,5,6,6+,iPadAir,Pro....
各种各样的机型层出不穷,为了适配我们不得不选择更为牛X的AutoLayout...
最开始我们用Autoresizing,然后苹果让我们用原生的那一长串布局,然后苹果发现那一串真的很长,于是出了VFL,然后发现VFL不太友好,又出了LayoutAnchors,但是最后我们选择了Masonry/SnapKit.....
大部分小伙伴还是用Masonry的....吧.....
虽然不更新了.....
其实用Masonry真的是非常的简单加方便,相信用过的小伙伴们都会说好....
But用自动布局来计算行高真的真的是非常消耗CPU,因为表格发生滚动行高就要进行计算,这是和之前用frame来计算行高是截然不同的,别看你只写了两句话(貌似第二句也不用写了,那么就一句话)...

self.tableView.estimatedRowHeight = 100;
self.tableView.rowHeight = UITableViewAutomaticDimension;

系统在后台要一直帮你拼命的计算行高啊啊啊啊啊!!!!!!
然后稍微不注意就会出现控制台发生警告,那一坨坨是不是看了都想死....
不过没关系,那个只要调整一下最后一条和contentView的约束的优先级<调低一点>(或者疯狂的用lessThan,greaterThan)就OK了...扯远了...
我们的话题是!!这样很消耗CPU啊啊啊啊.....
你想想:用户正在用你的APP滚动表格,也许他就是想浏览一下,就那么滚啊滚,结果电量掉的嗖嗖的,手机还发烫,那么你说你亲爱的用户会干嘛?给你打个电话?告诉你:亲爱的,你的表格滚起来有点烫手哦~~~~~~呵呵呵呵呵,碰到傲娇一点的就直接给你卸载了好不好....
好吧..扯了这么多没用的那么我们来说说解决办法吧...
那就是:缓存行高..
tableView有这么一个代理方法:

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath;

默认的情况下每个Cell会调用3次(貌似Xcode版本不一样这个值也不尽相同),是不是很惊悚,假如每个Cell都用自动布局,每个Cell系统都要忙碌的计算三次,表格能不卡吗.....
它的原理是这样的:
1.假如你没有设置预估行高呢,每个Cell都先计算一次,然后再计算你显示行的高度,一直到Cell能够填满你目前的屏幕,同时更新contentSize这样你就能滚了,哦,不..你的表格又能愉快的滚动了...
2.如果你设置了预估行高呢,那么系统会根据你设置的预估行高计算一下contentSize;至于你计算多少次也是根据你设置的预估行高来的,直到填满你的手机屏幕,更新contentSize;你要是给太大的预估行高,超出了预估的范围,她会顺序的计算后面的行高,一直到填满屏幕...
3.怎么说呢,使用预估行高在每个Cell的显示之前都需要计算,所以单个Cell的效率略低,但是整体的效率提高了啊.....
4.所以预估行高你别瞎给,尽量给的稍微准点....

言归正传.要怎么做呢
在这里我介绍两个方法
方法一: 用别人写好的第三方库,至于用什么就自行去谷歌或者GitHub上面搜索吧
方法二: 自己缓存.
如果你用MVC开发呢,就在你的模型属性中定义一个专门用来存储行高的属性,如果你用MVVM开发呢,那么就在你的视图模型中定义一个存储行高的属性(貌似我是在写废话......)
然后你再heightForRowAtIndexPath那个方法里面创建一个Cell<一定要用alloc/init创建,从缓存池中取会造成死循环,至于为什么自己去想!!!>,然后你把你的模型数据赋值给它,然后重头戏来了你要调用一下这个方法:[self layoutIfNeeded];从而Cell提前计算约束!提前计算约束!提前计算约束!
有了约束你就能获得最大的Y了,有了最大的Y,行高就缓存上了

在你的Cell里面添加一个这个方法

- (CGFloat)calculateRowHeight:(XXModel *)yourModel {
    self.model = yourModel;
    
    [self.view layoutIfNeeded];
    
    return CGRectGetMaxY(你最下面控件.frame);
}

最后你再heightForRowAtIndexPath里面返回的行高就是你计算出来的行高了,这样只用计算一次就可以了,并且还作为属性缓存起来,大大节省了CPU的开销....

最后的最后......假如你是ibireme的粉丝的话,他的一篇文章可以拜读一下,好吧我承认写的比我深刻多了........https://blog.ibireme.com/2015/11/12/smooth_user_interfaces_for_ios/

你可能感兴趣的:(UITableView表格性能优化(一))