我一直在对 UICollectionView 的性能进行大量调查。结论很简单。大量单元的性能很差。
编辑:抱歉,只需重新阅读您的帖子,您拥有的单元格数量应该没问题(请参阅我的其余评论),因此单元格复杂性也可能是一个问题。
如果您的设计支持它,请检查:
每个单元格都是不透明的。
单元格内容剪辑到边界。
单元格坐标位置不包含小数值(例如,始终计算为整个像素)
尽量避免重叠单元格。
尽量避免阴影。
原因其实很简单。很多人不理解这一点,但值得理解的是:UIScrollViews 没有使用 Core Animation 来滚动。我天真地认为他们涉及一些秘密的滚动动画“酱”,只是不时地要求代表们偶尔更新以检查状态。但实际上滚动视图是根本不直接应用任何绘图行为的对象。它们实际上只是一个应用数学函数抽象它们包含的 UIViews 坐标位置的类,因此 Views 坐标被视为相对于抽象 contentView 平面而不是相对于包含视图的原点。滚动视图将根据用户输入更新抽象滚动平面的位置(例如
现在,如果您要生成自己的集合视图布局对象,理论上,您可以生成一个 100% 反转底层滚动视图应用的数学转换的对象。这会很有趣但没用,因为当你滑动时,细胞似乎根本没有移动。但是我提出了这种可能性,因为它说明了集合视图布局对象与集合视图对象本身的操作与底层滚动视图非常相似。例如,它只是提供了一个机会,可以对要显示的视图的属性进行逐帧的附加数学转换,并且主要是位置属性的简单转换。
只有在插入或删除新单元格、移动或重新加载时才会涉及 CoreAnimation;通常通过调用:
- (void)performBatchUpdates:(void (^)(void))updates
completion:(void (^)(BOOL finished))completion
UICollectionView 为每一帧滚动请求单元格 layoutAttributes 并且为每一帧布局每个可见视图。UIView 是针对灵活性而非性能进行优化的丰富对象。每次布局时,系统都会进行许多测试来检查它的 alpha、zIndex、子视图、剪辑属性等。列表很长。这些检查以及任何由此产生的视图更改都将针对每个框架的每个集合视图项进行。
为确保良好的性能,所有逐帧操作都需要在 17 毫秒内完成。[由于您拥有的单元格数量,这根本不会发生]将这个条款括起来,因为我已经重新阅读了您的帖子,并且我意识到我误读了它。有了你拥有的细胞数量,应该不会有性能问题。我个人发现使用香草单元进行简化测试,只包含一个缓存图像,在 iPad 3 上测试的限制是大约 784 个屏幕单元,然后性能开始下降到 50fps 以下。
在实践中,您需要保持低于此值。
就我个人而言,我正在使用自己的自定义布局对象,并且需要比 UICollectionView 提供的更高的性能。不幸的是,我没有运行上面的简单测试,直到开发路径的某个方向,我意识到存在性能问题。所以我将重新设计 UICollectionView 的开源后端端口 PSTCollectionView。我认为有一种解决方法可以实现,因此,仅对于一般滚动,每个单元格项目的层都是使用绕过每个 UIView 单元格布局的操作编写的。这对我有用,因为我有自己的布局对象,并且我知道何时需要布局,并且我有一个巧妙的技巧,可以让 PSTCollectionView 在此时回退到其正常操作模式。我检查了调用顺序,看起来并不太复杂,它也似乎完全不可行。但可以肯定的是,它不是微不足道的,在我确认它会起作用之前,必须进行一些进一步的测试。