Osk*_*kar 53 objective-c ios uicollectionview
我正在开发一个自定义UICollectionViewLayout
按日/周/月组织的单元格.
它不是滚动平滑,看起来滞后是由[UICollectionView _updateVisibleCellsNow]
每个渲染循环调用引起的.
性能对于<30项是可以的,但在大约100或更高时,它非常慢.这是UICollectionView和自定义布局的限制,还是我没有给视图足够的信息来正确执行?
来源:https://github.com/oskarhagberg/calendarcollection
布局:https://github.com/oskarhagberg/calendarcollection/blob/master/CalendarHeatMap/OHCalendarWeekLayout.m
数据源和代理:https://github.com/oskarhagberg/calendarcollection/blob/master/CalendarHeatMap/OHCalendarView.m
时间档案:
更新
也许它徒劳无功?一些测试与普通UICollectionViewController
带UICollectionViewFlowLayout
被给予大约的细胞/屏幕结果相同的量以类似的时间曲线.
我觉得它应该能够在没有抖动的情况下一次处理~100个简单的不透明单元.我错了吗?
Alt*_*mac 93
另外不要忘记尝试栅格化单元格的图层:
cell.layer.shouldRasterize = YES;
cell.layer.rasterizationScale = [UIScreen mainScreen].scale;
Run Code Online (Sandbox Code Playgroud)
没有那个我有10 fps,并且用55fps的速度!我对GPU和合成模型并不是很熟悉,所以它对我来说并不完全清楚,但基本上它只在一个位图中展平所有子视图(而不是每个子视图一个位图?).无论如何,我不知道它是否有一些缺点,但它的速度要快得多!
The*_*ind 17
我一直在对UICollectionView性能进行大量调查.结论很简单.大量细胞的表现很差.
编辑:道歉,只是重新阅读你的帖子,你有的单元格数量应该没问题(参见我的评论的其余部分),因此单元复杂性也可能是一个问题.
如果您的设计支持它,请检查:
每个细胞都是不透明的.
单元格内容剪辑到边界.
单元格坐标位置不包含小数值(例如,总是计算为整像素)
尽量避免重叠细胞.
尽量避免阴影.
其原因其实很简单.很多人不理解这一点,但值得理解:UIScrollViews不使用Core Animation进行滚动.我天真的信念是,他们涉及一些秘密的滚动动画"酱",只是偶尔要求代表偶尔更新,以检查状态.但实际上滚动视图是根本不直接应用任何绘图行为的对象.它们实际上是一个类,它应用抽象它们包含的UIViews的坐标位置的数学函数,因此视图坐标被视为相对于抽象contentView平面而不是相对于包含视图的原点.滚动视图将根据用户输入(例如,滑动)更新抽象滚动平面的位置,并且当然还存在物理算法,其给予平移坐标位置"矩形".
现在,如果您要生成自己的集合视图布局对象,理论上,您可以生成一个100%反转基础scrollview应用的数学转换的对象.这将是有趣但无用的,因为当你滑动时,细胞根本不会移动.但我提出了这种可能性,因为它说明了使用集合视图对象本身的集合视图布局对象对底层的scrollview执行了非常类似的操作.例如,它简单地提供了通过要显示的视图的属性的帧转换来应用附加数学帧的机会,并且在主要情况下,这将仅是位置属性的翻译.
只有在插入或删除新单元格时,才会移动或重新加载CoreAnimation; 最常通过调用:
- (void)performBatchUpdates:(void (^)(void))updates
completion:(void (^)(BOOL finished))completion
Run Code Online (Sandbox Code Playgroud)
UICollectionView为每个滚动帧请求单元格layoutAttributes,并为每个帧布置每个可见视图.UIView是丰富的对象,优化灵活性而不是性能.每次布局时,系统都会进行一些测试来检查它的alpha,zIndex,subViews,裁剪属性等.列表很长.正在为每个帧的每个集合视图项执行这些检查以及对视图的任何更改.
为了确保良好的性能,所有逐帧操作都需要在17ms内完成.[随着你拥有的细胞数量,这根本就不会发生]括号内的这个条款,因为我重新阅读了你的帖子,我意识到我误读了它.根据您拥有的单元数量,不应存在性能问题.我个人发现使用香草细胞进行简化测试,只包含一个缓存图像,在iPad 3上测试的极限是大约784个屏幕上的单元,然后性能开始下降到50fps以下.
在实践中,你需要保持低于此值.
就个人而言,我使用自己的自定义布局对象,需要比UICollectionView提供的更高的性能.不幸的是,我没有运行上面的简单测试,直到开发路径的某个方向,我意识到存在性能问题.我是这样的,我将重新编写UICollectionView,PSTCollectionView的开源后端口.我认为有一个可以实现的解决方法,只是对于一般滚动,每个单元项的层是使用绕过每个UIView单元的布局的操作编写的.这对我有用,因为我有自己的布局对象,我知道何时需要布局,我有一个巧妙的技巧,允许PSTCollectionView此时回退到正常的操作模式.我已经检查了调用序列,它看起来并不太复杂,也不会显得不可行.但可以肯定的是,这是非常重要的,在我确认它可行之前,必须进行一些进一步的测试.
一些可能有用的观察结果:
我能够重现这个问题,使用流媒体布局一次可见大约175个项目:它在模拟器中顺畅滚动但在iPhone 5上落后于地狱.确保它们是不透明的等等.
最终花费最多时间似乎是在内部使用可变的NSDictionary _updateVisibleCellsNow
.既复制字典,又按键查找项目.键似乎是UICollectionViewItemKey,该[UICollectionViewItemKey isEqual:]
方法是最耗时的方法.UICollectionViewItemKey含有至少type
,identifier
和indexPath
性质,以及其包含的属性indexPath比较[NSIndexPath isEqual:]
花费时间最多的.
由此我猜测UICollectionViewItemKey的哈希函数可能缺乏,因为isEqual:
在字典查找期间经常调用它.许多项目可能以相同的哈希结尾(或在相同的哈希桶中,不确定NSDictionary如何工作).
出于某种原因,1节中的所有项目都比较快,而每个节目中有7个项目.可能是因为它在NSIndexPath中花费了太多时间isEqual,如果行首先差异,或者UICollectionViewItemKey获得更好的哈希值,则会更快.
老实说,UICollectionView在每个滚动帧上执行繁重的字典工作时感觉非常奇怪,如前所述,每次帧更新需要<16ms才能避免滞后.我想知道那些字典查找是否是:
希望我们今年夏天在WWDC期间看到一些改进,或者如果其他人能够弄清楚如何解决它.
这是Altimac的答案转换为Swift 3:
cell.layer.shouldRasterize = true
cell.layer.rasterizationScale = UIScreen.main.scale
Run Code Online (Sandbox Code Playgroud)
此外,应该注意,此代码位于cellForItemAtIndexPath的collectionView委托方法中.
还有一个提示 - 查看应用程序的每秒帧数(FPS),打开仪器下的核心动画(见图).
问题不在于您在集合视图总计中显示的单元格数量,而是一次显示在屏幕上的单元格数量.由于单元格尺寸非常小(22x22),因此屏幕上一次可见154个单元格.渲染这些中的每一个都会降低您的界面速度.您可以通过增加Storyboard中的单元格大小并重新运行应用程序来证明这一点.
不幸的是,你无能为力.我建议通过避免剪切到边界并尝试不执行来缓解问题drawRect:
,因为它很慢.
大拇指上面的两个答案!这是您可以尝试的另外一件事:UICollectionView
通过禁用自动布局,我在性能上有了很大的改进.虽然您必须添加一些额外的代码来布局单元格内部,但自定义代码似乎比自动布局快得多.
除了列出的答案(光栅化、自动布局等)之外,您可能还需要检查可能会降低性能的其他原因。
就我而言,每个 UICollectionViewCell 都包含另一个 UICollectionView(每个 UICollectionView 大约有 25 个单元格)。当每个单元格加载时,我调用内部 UICollectionView.reloadData(),这会显着降低性能。
然后我将 reloadData 放入主 UI 队列中,问题就消失了:
DispatchQueue.main.async {
self.innerCollectionView.reloadData()
}
Run Code Online (Sandbox Code Playgroud)
仔细研究这些原因可能也会有所帮助。
归档时间: |
|
查看次数: |
33410 次 |
最近记录: |