提升含有动态高度UITableViewCell的UITableView的运行效率

来源:互联网 发布:ansys软件16.0 编辑:程序博客网 时间:2024/03/29 01:39

http://pizi.me/66

提升含有动态高度UITableViewCell的UITableView的运行效率

在使用UITableView的时候可能会遇到这种情况:UITableViewCell中的内容来自网络端,可能需要根据内容的生成高度不一致的UITableViewCell。本文介绍一种常用方式,并且给出一定优化的建议。

1.常规解决方式

UITableView 需要实现 delegate中的 cell的高度定义

以及 dataSource 中的

返回具体cell的函数。但是 heightForRowAtIndexPath 的代理总是先于cellForRowAtIndexPath 调用, 因此这里有一个小矛盾,即,需要返回 cell 高度的时候,实际的cell还没填入内容。

一般的解决方式是,在 cell 中使用一个方法

或者其他的类似方法先根据内容计算一遍Cell的高度,然后在实际Cell生成的时候,再把内容填进去。

在这里,实际上对于同一条数据,内容被加载了两次,从而造成了运力的浪费;在计算富文本或者大量数据的时候,UITableView会出现卡顿现象。

 

2.使用NSCache

NSCache 一言蔽之是一个很傻瓜式的缓存控件,存取方式类似于NSDictionary,工作方式与苹果的内存管理体系相一致,在内存吃紧的时候,它会自动释放存储的对象。所以,你项目中任何你称之为缓存却不是 NSCache 对象的东西都应该被换成 NSCache(在使用它之前,我自己写了很多带cache的NSArray 或者 NSDictionary,现在想来,这些都是不合理的)。

在这里,我们需要做的,就是在计算高度的时候就生成一个UITableViewCell 并存入 NSCache , 需要返回 Cell 时 先从缓存池中寻找那个Cell;如果没有找到,则使用UITableView 的重用机制重用;如果还是找不到可用重用的Cell,那只有新建一个UITableViewCell。

部分代码

这里使用 “indexPath.section- indexPath.row” 作为Key, YQTableViewCell 为自定义Cell ,_cellCache为一个NSCache 对象。

小演示 :Demo  Zip

注意,因为 使用 “indexPath.section- indexPath.row”,所以如果数据长度发生改变,如增加了数据等,则需用 将 _cellCache 清空。

 

 

 

本条目发布于2014年6月25日。属于iOS分类,被贴了 iOS、UITableView 标签。

文章导航

 基于LNMP+uWSGI部署Django应用粗略地在iOS中使用URLManager架构 
最新最早最热
  • 20条评论 
  • 4条新浪微博
  • Milu
    Milu

    不错,网上其他方法都不行。

    • 痞子
      痞子

      THX

      • Milu
        Milu

        我最近遇到比这个更难的问题。就是tableview的高度能一次展示完所有的cell。

        这种情况下,每次刷新没法清空_cellCache。因为清空了会重新生成cell。比如我有50个cell,每次我加载新的数据,我不能把这50个的缓存都清掉重新计算。这个太耗费性能了。


        所以,就不清空。可是不清空的话,每次加载新的cell,旧的cell会被系统设置成hidden=yes。导致旧的cell全部都是隐藏的。


        彻底没撤了,有啥解决办法吗?

        • Milu
          Milu

          自己找到答案了。彻底去掉tableview自身的重用机制就行了。

          • 痞子
            痞子

            彻底去除始终不是一个很好的办法

            • milu
              milu

              那你有啥好方法吗

              • 痞子
                痞子

                1. 对一条数据而言,只要数据不变,它生成的高度是一定的,那么可以这么认为,一条数据对应一个高度,除非修改数据内容,否则只使用缓存的高度,如果数据内容修改了,则需要重置该条消息的高度缓存,貌似不会出现全部清除高度缓存的情况,你可以改改我这个 demo 改成只缓存高度而不是 cell ;一般的数据都有 ID 吧, 唯一标识应该很好找的.
                2.如果所有的 cell 都在一屏之内,重不重用效果都是一样的

                • milu
                  milu

                  你说的这些我看了两次没看出啥。
                  你说缓存高度而不是cell。那问题来了。heightForRowAtIndexPath 先于cellForRowAtIndexPath执行。那么在执行heightForRowAtIndexPath 的时候,我必须填充cell的数据,并获得高度进行缓存。可是顺着你的意思,不缓存cell。那么cellForRowAtIndexPath执行的时候,我还得再填充数据,再生成cell给他。那不是两次填充了吗?那你这篇文章不就是为了解决这个问题而存在的吗?缓存的高度干啥子用来着了?

                  • 痞子
                    痞子

                    这个方案和本篇的文章有点不一致,场景是出现频繁滑动,cell 非常巨大的场景~

                    • milu
                      milu

                      你这个方案是解决“场景是出现频繁滑动,cell 非常巨大的场景~”还是本篇文章解决的?没清楚。。

  • lynulzy-
    lynulzy-

    第一种方法那个没什么用吧?

  • rorofromlatrobe
    rorofromlatrobe

    缓存cell 比缓存高度 快多少

  • rorofromlatrobe
    rorofromlatrobe

    请问一下 如果我在当前页面使用cell 缓存大约缓存了100个 我刷新或者离开 我需要清除缓存 清理过程会不会很耗性能

  • rorofromlatrobe
    rorofromlatrobe

    你的demo有点问题啊 你prepare 的时候怎么没有计算高度 直接取了cell.bounds.height呢

  • 最励志网
    最励志网

    无意溜达到了你的网站 留下足迹

  • 阿刀
    阿刀

    你的博客好棒啊,欢迎回访哦

  • 恼痰勤18
    恼痰勤18

    [星星眼儿]

  • 笨小子
    笨小子

    楼主搞笑吧,UITableViewCell本身就是复用的,设计原理就是为了节省内容,在有限的屏幕显示可见的cell,然后重复利用这些cell,你只需要缓存一下cell的高度就好了,这样cell复用更新一下内容就好了,不必再次计算高度,有利于优化性能

  • nogicwit
    nogicwit

    你都把每个cell计算创建存入NSCache了,那还要cell的重用机制干啥,如果有1000个cell,页面只需显示10个,浪费了大量内存

    • 痞子
      痞子

      好多富文本的 cell 填充数据 生成界面是非常卡的,NSCache 是会自动释放的,类似 Linux 的内存机制 ,占用越多越好, 不够用时再释放;这篇文章 只是为了解决一些特定的场景,原思路也是来自一个包含大量富文本 cell的 demo,这里主要解决 渲染 动态cell 卡的问题~

0 0
原创粉丝点击