我已经实现了自己的 Collection View 布局,它是 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
方法仍然仅针对可见矩形内的属性调用。
这是预期的行为吗?如果是的话,如果 Collection View 本身过滤我的代码中的属性,其目的是什么?我没有发现任何性能问题。
是否可以强制collectionview调用cellForItemAt
对于所有返回的属性?
最佳答案
是的,这是 Collection View 的预期行为。在 UICollectionViewLayout
的文档中苹果表示(强调):
The job of a layout object is to determine the placement of cells, supplementary views, and decoration views inside the collection view’s bounds and to report that information to the collection view when asked.
然后继续:
The collection view asks its layout object to provide layout information for these elements at many different times. Every cell and view that appears on screen is positioned using information from the layout object.
代码中过滤属性的目的是提高性能。主要有三个因素影响布局对象的性能:
- Collection View 数据源中的项目数。
- 确定布局属性的复杂性。
- 自定义布局属性所需的内存量。
在上述条件不友好的情况下(你有很多元素,计算属性非常复杂并且你的自定义属性需要大量内存)提前计算所有属性是不可行的因为预先计算这些值需要花费大量时间和资源,因此您必须在 layoutAttributesForElementsInRect
中实现一些逻辑,而不是将它们缓存在 prepare
函数中> 用于计算布局属性。在这种情况下,您可以使用可见矩形参数仅计算屏幕中可见的单元格和 View 的属性值。
关于强制 Collection View 为所有返回的属性调用 cellForItemAt
,我不确定这样做的值(value)是什么,因为它只会使用其中的几个。实现这一目标的唯一方法是拥有一个与您所显示内容的大小相同的 Collection View ,以便所有单元格都被视为可见。但是,这样做首先会使使用 Collection View 的意义失效,因为单元格不会被重用,也不会滚动。如果您试图修复 Collection View 项目的一些奇怪的动画,这不是正确的方法。
关于ios - UICollectionViewLayout.layoutAttributesForElementsInRect 的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59357522/