ios - 使用缓存的 UICollectionViewLayoutAttributes 子类化 UICollectionViewLayout
问题描述
我正在尝试了解其UICollectionViewLayout
工作原理并找到了此示例代码。
https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
在示例代码(以及我能找到的所有其他示例)中,它具有cachedLayoutAttributes
对象并计算prepare()
.
我发现此模式有 2 个问题。
一是如果数据源的数量足够大,计算prepare()
方法中的所有内容都需要时间(并且每当collectionView的布局发生变化时都会重新计算),因此看起来效率不高。
另一个问题是没有机会layoutAttributesForItem
或layoutAttributesForSupplementaryView
被叫。仅layoutAttributesForElements
被调用,似乎足以布置单元格/补充视图。
我阅读了文档,但它只说必须覆盖这些方法。我最好的猜测是我应该使用覆盖这些方法来返回适当的UICollectionViewLayoutAttributes
并从layoutAttributesForElements
. 但是layoutAttributesForElements
,每当用户滚动 UICollectionView 时都会调用它,因此它似乎也不是很有效。
我想知道是什么情况layoutAttributesForItem
并被调用,如果数据源的数量很大layoutAttributesForSupplementaryView
,计算的最佳方式/地点/时间是什么/何时/何地。UICollectionViewLayoutAttributes
更新
感谢您的评论。然而,它似乎是关于失效周期的优化。
旨在支持失效上下文的布局对象可以使用 UICollectionViewLayoutInvalidationContext 对象中的信息来优化它们在失效周期期间的行为。
这意味着UICollectionViewLayoutAttributes
已经设置并且只有必要的部分无效,对吗?
UICollectionViewLayoutAttributes
那么,第一次应该在哪里计算呢?如果我错了,请告诉我。
解决方案
一是如果数据源的数量足够大,计算
prepare()
方法中的所有内容都需要时间(并且每当collectionView的布局发生变化时都会重新计算),因此看起来效率不高。
是的,它看起来效率不高。使prepare()
计算尽可能高效是您的工作。
例如:只计算一部分属性,当使用 .scroll 改变它的位置时计算更多shouldInvalidateLayout(forBoundsChange:)
。但是要小心这种方法,因为它可能会使每个像素滚动的布局无效。
prepare()
调用方法不仅仅是为了好玩,它会通知您某些内容已更改并且需要重新计算!但是很难获得有关变化的信息。您可以在准备之前检查IGListKit如何获取有关更改的信息:链接。
另一个问题是没有机会
layoutAttributesForItem
或layoutAttributesForSupplementaryView
被叫。仅layoutAttributesForElements
被调用,似乎足以布置单元格/补充视图。
layoutAttributesForElements(in:)
首先调用,因为该集合不知道您的单元格和补充视图的顺序。所以它要求指定矩形中的所有属性。尝试插入/移动/删除/重新加载单元格,我相信layoutAttributesForItem(at:)
可能会被调用。或者可能不是。但是您不必担心,因为您已经拥有属性缓存。
由于您缓存属性layoutAttributesForElements(in:)
应该足够高效,并且看起来像这样:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributes
.reduce(into: [UICollectionViewLayoutAttributes](), { $0 += $1.filter({ $0.frame.intersects(rect) }) })
}
我个人建议查看一些困难的开源布局。UICollectionViewLayout
您将从任何简单的示例项目中获得有关比较信息的更多信息。
推荐阅读
- angular - Angular 7无法在获取带有地图的Web服务中发送标头
- .net - 使用 Simple Injector .NET 进行依赖注入,找不到类型或命名空间
- excel - 将值复制并粘贴到工作簿中每个工作表的数据表末尾
- javascript - 使用 Parceljs 时,为 Prime React 组件包含 css 文件的最佳方法是什么?
- python - Python三元组到元组
- java - 退出VM后如何在其中创建临时文件并删除
- php - 如何在 where() 函数中给出条件以使表中的记录不等于零
- cordova - 是否可以使用“Set-Cookie”响应标头在 Cordova 中设置 cookie?
- python - from urllib3.util.ssl_ import ( ImportError: cannot import name ssl
- python - 使用 tf.distribute 时,如何避免在每个 tf.keras 时期重新填充我的 tf.data 洗牌缓冲区?