ios - UICollectionViewLayout.layoutAttributesForElementsInRect 的行为
问题描述
我已经实现了我自己的从 UICollectionViewLayout 子类化的集合视图布局。在prepare
我计算和缓存布局属性。在layoutAttributesForElementsInRect
我过滤掉那些不正确的:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return itemAttributesCache.filter { $0.frame.intersects(rect) }
}
我预计func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell
将为已返回的每个索引路径调用数据源方法layoutAttributesForElementsInRect
但是我发现如果我只是返回整个属性集:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return itemAttributesCache
}
cellForItemAt
仍然只为可见矩形内的属性调用方法。
这是预期的行为吗?如果是的话,在我的代码中过滤属性的目的是什么,如果集合视图本身可以做到这一点?我没有发现任何性能问题。
是否可以强制 collectionview 调用cellForItemAt
所有返回的属性?
解决方案
是的,这是集合视图的预期行为。在UICollectionViewLayout
Apple 的文档中说(强调):
布局对象的工作是确定集合视图边界内的单元格、补充视图和装饰视图的放置,并在被询问时将该信息报告给集合视图。
然后继续:
集合视图要求其布局对象在许多不同时间为这些元素提供布局信息。屏幕上出现的每个单元格和视图都使用来自布局对象的信息进行定位。
代码中过滤属性的目的是提高性能。主要有三个因素会影响您的布局对象的性能:
- 集合视图数据源中的项目数。
- 确定布局属性的复杂性。
- 您的自定义布局属性所需的内存量。
在上述条件不友好的情况下(您有很多项目,计算属性非常复杂,您的自定义属性需要大量内存)提前计算所有属性是不可行的,因为它会预先计算这些值需要花费大量时间和资源,因此您不必在函数中缓存它们,而是必须在计算布局属性prepare
中实现一些逻辑。layoutAttributesForElementsInRect
在这种情况下,您使用 visible rect 参数仅计算将在屏幕中可见的单元格和视图的属性值。
关于强制集合视图调用cellForItemAt
所有返回的属性,我不确定这样做的价值是什么,因为它只会使用其中的几个。实现这一点的唯一方法是拥有一个与您正在显示的内容大小相同的集合视图,以便所有单元格都被视为可见。但是,这样做首先会使使用集合视图的意义无效,因为单元格不会被重用,也不会滚动。如果您试图用集合视图项目修复一些奇怪的动画,这不是要走的路。
推荐阅读
- c# - DynamoDB Scan 似乎无法识别我的列表
> - ansible - 检查两个变量是否都已定义且不为空
- elasticsearch - 从自定义 FieldBridge 索引 LongField 的问题
- swift - Swift:防止双精度值删除小数
- html - 如何解决 w3 验证错误错误值?
- apache-spark - 无法执行数据帧 show() 或使用 sql:Zeppelin
- android - 无法使用 Android Retrofit 访问 JSON 中的数据
- c# - ASP.NET 核心 WebApi。SQL 视图的 OData 配置
- python - 如何以pythonic方式检查字典的某些变量和特定键是否为None?
- php - 在 PHP 中将 GMT 日期戳转换为我的时区