美文网首页不明觉厉iOSiOSiOS
UITableView性能优化-一次面试后的反思总结

UITableView性能优化-一次面试后的反思总结

作者: Binboy_ | 来源:发表于2015-10-20 22:32 被阅读7667次

    面试的时候遇到这个问题,竟一时没有全答上来,于是Google了一下,常见的一些譬如Cell重用设计统一Cell缓存Cell高度Cell数据资源缓存,这些其实平时都在用,但因为平时还是缺乏总结,回答这么个问题的时候却只想到说“==重用==”、“==缓存==”,道理你都懂,但这样极度概括的答案在面试过程中并不是什么好答案,深有体会~

    另外,也有自己平时很少用而想不起来的,就是性能要求更高一些的话Cell中用到的视图控件可以尽可能自行drawRect

    面试结果也未可知,便先吃一堑长一智,趁热将其总结总结。

    Cell重用机制

    这是TableView的基本使用,仅作简单归纳。

    [tableView dequeueReusableCellWithIdentifier:(NSString *)identifier forIndexPath:(NSIndexPath *)indexPath];

    使用这个方法需要提前注册Cell到对应的tableView:

    • 1、Stroyboard: 定义Cell的Prototype,并设置其Reusable Identifier

    这里值得一提的是:Cell的Prototype最好高度抽象统一,越少越好,因为每个不同的Prototype都有其对应的Cell重用池,创建的Cell就越多,重用效率也就越低。(详见以下设计统一规格的Cell)

    • 2、Xib自定义:

    [registerNib:(nullable UINib *)nib forCellReuseIdentifier:(NSString *)identifier];

    • 3、代码自定义:

    [registerClass:(nullable Class)cellClass forCellReuseIdentifier:(NSString *)identifier];

    设计统一规格的Cell

    统一Cell的规格,不仅能减少设计不同Cell所需要代码量和nib文件,更重要的是能提高Cell的重用率,提升TableView整体性能。

    • 等高的Cell好设计,显示不同数据就可以了,无须多费篇幅。

    • 动态计算高度的Cell也应该统一设计,比如下面这个赤兔的例子

    虽然看起来有些不一样,但实际上整体构成是统一的,都是由头像、姓名、公司、职位、时间、内容、其他(图片、网页链接、视频等附件)以及转发、赞、和评论三个底部按钮,这些控件的显示可根据模型中的不同数据在代码当中动态控制就好了。

    创建ViewModel,计算并储存Cell的UI尺寸信息

    @interface BYTweetViewModel : NSObject

    @property(strong, nonatomic) BYTweetModel *dataModel; //原始数据模型

    @property(assign, nonatomic) CGFloat cellHeight; //Cell 高度

    • (void)calculateCellHeight; //计算高度

    @end

    这里有个坑需要注意

    在iOS中,系统是先调用“tableView:heightForRowAtIndexPath:”获取每个Cell即将显示的高度,确定整个UITableView的布局。然后才调用“tableView:cellForRowAtIndexPath”获取Cell。因此,使用了ViewModel来保存UI信息,Cell高度的计算和使用的时机需要特别留意。

    提前处理Cell需要显示的数据资源

    在Cell显示之前,将从服务器加载获取到的原始数据在ViewModel中进行提前处理,一般包括图片的加载和压缩、富文本的多样化显示(NSString->NSAttributeString)。

    这时ViewModel可能会是这样

    @interface BYTweetViewModel : NSObject

    @property(strong, nonatomic) BYTweetModel *dataModel; //原始数据模型

    @property(assign, nonatomic) CGFloat cellHeight; //Cell 高度

    //需要显示的数据内容

    @property(strong, nonatomic) NSAttributeString *titleToShow;

    @property(strong, nonatomic) NSAttributeString *contentToShow;

    • (void)calculateCellHeight; //计算高度

    • (void)handleSourceDataModel;

    @end

    其它

    我了解的,也是常用的方案基本是以上几种了,总之呢,还是可以回到我面试时候的高度概括,尽可能“重用”、“缓存”,用空间换取时间。

    另外还有些更为极致的一些方式和操作细节也就不深入展开了,大致整合一下。

    • Cell中的view尽可能不要使用透明

    • 减少子视图的层级关系

    • 图片载入在后台进程进行,滚出可视范围的载入进程cancel掉

    • 图片资源尽可能使用PNG

    • ……

    参考

    知乎上有个讨论,阐述了许多各种各样不同的思路,虽然很少情况需要那么极致,但也可以在必要的时候尝试看看,不过相应的代码量增加了,可一定要注意避免各种莫名bug出现哦~

    知乎:如何加强 iOS 里的列表滚动时的顺畅感?

    相关文章

      网友评论

      • 千寻_544f:Mark,整理的不错。
      • 简洁的想法:在缓存cell高度的问题中,什么时候计算cell高度呢?
        简洁的想法:@简洁的想法 是在网络请求之后,计算cell高度吗
      • PPPan:> 性能要求更高一些的话Cell中用到的视图控件可以尽可能自行drawRect。

        drawRect 是最容易造成失帧的原因,作者不妨写个 Demo 试试。
      • a879733dea2c:说的很不错。Mark 一下。
      • 6fdb0c58ceca:关于赤兔那个例子,我还真不知道一个图和9个图该怎么搞,我们现在的app,分别是1个图,2个图,3个 图的排列方式,我用的collectionView,感觉很卡,可能不算是图片这里的原因,但是有一点吧
        1b2ae550dc99:@碧野MAX 这个和新浪微博的效果一样吧?!
      • 9ca89407f2e6:总结挺好的!
        土豆董:@即时阅读 赞
      • 许还真:期待楼主出一份代码。
      • 会飞的猪X:写的很好 学习了
      • Shumin_Wu:用代码自定义的cell,使用时要做 layer 栅格化处理
      • soullink2011:不错,很不错,个人见解补充一点,尽量减少cell中子视图透明化以及做切圆操作,在layer层渲染图层时会涉及上下文切换以及离屏渲染之类的,系统开销会很大,特别是在cell视图很复杂的时候,由于渲染问题导致的内存开销会让你的tableview非常卡顿,如果有误欢迎指正
        对酒当歌的夜:@MJ1513 说的不错.比如cell中需要设置头像圆形直接设置圆角会很卡,一般用Quartz2d把拿到的图片处理一遍在给cell使用就好了
      • 9814c09cceda:收藏了
      • leadhxyh168:好啊!
      • 叶舞清风:很不错

      本文标题:UITableView性能优化-一次面试后的反思总结

      本文链接:https://www.haomeiwen.com/subject/ictthttx.html