改善iPhone UITableView滚动性能的技巧?


89

我有一个uitableview,它在每个单元格中加载相当大的图像,并且单元格的高度根据图像的大小而变化。滚动性能不错,但有时会有些生涩。

我在FieryRobot博客上找到了这些技巧:

易用的玻璃滚动视图

更加方便的滚动浏览

有没有人有任何改善uitableview滚动性能的提示?


如果您需要缓存像元高度(计算起来可能很昂贵并且也经常使用),我举一个例子。仅在适合您的应用程序时使用。 stackoverflow.com/questions/1371223/...
保罗·德·兰格

Answers:


156
  1. 缓存行的高度(表视图可以经常请求此高度)
  2. 为表中使用的图像创建最近最少使用的缓存(并在收到内存警告时使所有不活动的条目无效)
  3. 在绘制一切UITableViewCelldrawRect:,如果不惜一切代价尽量避免子视图(或者,如果你需要的标准的辅助功能,内容画面的drawRect:
  4. 使您UITableViewCell的图层不透明(如果有的话,内容视图也一样)
  5. 使用UITableView示例/文档推荐的reusableCellIdentifier功能
  6. 避免未预先烘焙到UIImages中的渐变/复杂的图形效果

5
此外,下载的图像应按比例缩小到imageView的大小,然后再显示在单元格上!
佐尔坦Matók

4
我想补充一下我过去几年的经验-具有透明单元格可能永远不会导致滚动性能变差。我们有一个带有非常复杂单元格(超过20个子视图)的应用程序,并且透明显示背景。通过适当的优化,即使在3GS上,透明度也不会造成任何影响。实际上,最慢的事情是在没有足够的单元格可以从表视图中退出之前,笔尖加载。如果使用子视图,只需确保具有有效的层次结构,而无需使用drawRect。
Accatyyc 2014年

@Accatyyc,看来我有同样的问题。当没有足够的单元格要出队时,会有一个小的滞后;当3-4个单元格出队时,滚动是平滑的。有什么方法可以预加载单元格,以便在滚动时有一些单元可以出队并且不加载NIB文件?
Tiois '16

@Tiois当然有。您需要使用使单元出队的旧方法(不要注册类/笔尖,但是如果dequeueCellWithIdentifier:返回nil,则创建它们)。这样,您可以在表格视图甚至不存在之前创建一组单元格,例如,之前创建20个单元格。然后,您无需从cellForRowAtIndexPath:中创建新的缓存,而是先从自己的缓存中拉出它们,直到其为空。
Accatyyc

我正在使用UICollectionView并面临相同的问题。在我的自定义单元笔尖文件中。我在垂直UIstackView中使用了几个子视图,包括UIwebView和UIImageView。当我滚动列表时,重用的单元格需要花费大量时间来调整其大小,并且滚动看起来非常不稳定。
Mansuu ....

40
  1. 如果要子类化 UITableViewCell,请不要使用Nib,而应使用代码编写。它比加载Nib文件快得多。
  2. 如果您使用的是图像,请确保要对其进行缓存,这样就不必每次从文件中加载多个文件(如果有内存,您会惊讶地发现有多少空间图像会占用空间)。
  3. 使尽可能多的元素不透明。同样,请不要使用透明的图像。

3
别担心...那是巨魔。好答案!
Steav

79
投反对票的原因可能是“避免鸟嘴”是提高性能的不良建议。如果要重用单元格,则滚动时根本不会从笔尖重建单元格。
史蒂芬·费舍尔

6
根据可可与Love的研究,笔尖的速度相当,或者更快。cocoawithlove.com/2010/03/…–
MaxGabriel

例如,在快速滚动期间,当表分配和取消分配单元格时,使用Nib的@Steven Fisher可能会比较慢。
Sound Blaster

3
构建细胞时,使用NIB 可能会较慢。如果您正在使用单元回收,则仅分配了足够的单元来填充屏幕。最多只能说10个。滚动时不会创建单元格。他们只是被重用,而不是被释放和重新分配。而且,当然,无需花费任何费用。所以不,这是不正确的。
史蒂芬·费舍尔

34

Tweetie背后的开发人员对此进行了广泛的编写,并提供了一些代码来演示该应用程序是如何完成的。基本上,他/她主张为每个表单元格提供一个自定义视图,并手动进行绘制(而不是使用Interface Builder进行子视图以及其他选项)。

快速浏览带有宜人的视图

此外,Apple在其TableViewSuite教程中更新了自己的TableView示例代码(也许是对此做出的回应?)

TableViewSuite


1
这是一个很棒的解决方案。我很好奇如何将UIButton添加到cellView中?它是在drawRect方法中绘制的吗?
Sukitha Udugamasooriya 2011年

1
@beno,您的链接似乎已断开(第一个链接),您有机会将我们的文章放在原始文章上吗?
2012年


由于原始版本不存在,因此添加了指向Web存档的链接
Ralph Willgoss 13-4-25

1

UITableView滚动的#1性能杀手是在任何单元格视图层上绘制阴影,因此,如果滚动性能很重要,则不要绘制阴影,除非基本上不会降低主线程的速度。

认为必须这样说,因为没有一个公认的答案提到阴影和层。:+)


6
如果问题是阴影,则将这两行代码相加,并且一切运行良好。self.layer.shouldRasterize = YES; self.layer.rasterizationScale = UIScreen.mainScreen.scale;
PedroRomão2015年

0

UITableView滚动性能的任何问题都可以使用其他答案中已经描述的技术来解决。但是,很多时候性能不佳是由于某种固有的错误或重复性造成的。

这一事实UITableView重用细胞,而事实上,每一个细胞都需要有自己的形象-一起使得该解决方案有点复杂。通过一般方法的解决方式,在这里我总结了应注意的事项:

  1. 从REST /数据库将数据加载到数据源中。此步骤应在后台完成,最终将使用dispatch_async和GCD队列。
  2. 创建并初始化相关的数据模型对象,并将它们放入数组中
  3. [tableView reloaddata]
  4. 在内部cellForRowAtIndexPath,包括将设置数组的正确数据模型对象中的数据(文本)的代码。
  5. 现在图像也可能以URL的形式出现,因此由于表视图完成了单元重用,因此此步骤可能有点古怪。事实的核心是使用异步队列再次从设备缓存/ URL加载图像,然后将其设置为正确的cell.image(无论您的单元格图像属性如何)。

为避免出现问题,请参阅本表中有关在表视图内延迟加载图像的教程。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.