我已经实现了我自己的从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 的文档中说(强调):

布局对象的工作是确定单元格,补充视图和装饰视图在集合视图的边界中的位置,并在被询问时将该信息报告给集合视图。

然后继续:

集合视图要求其布局对象在许多不同的时间提供这些元素的布局信息。使用布局对象中的信息来定位屏幕上出现的每个单元格和视图

在代码中过滤属性的目的是提高性能。主要有三个因素影响布局对象的性能:

  • 集合视图数据源中的项目数。
  • 确定布局属性的复杂度。
  • 自定义布局属性所需的内存量。

  • 在上述条件不友好的情况下(您有很多项目,计算属性非常复杂,并且自定义属性需要大量内存),事先计算所有属性是不可行的,因为这样做会需要花费大量时间和资源来预先计算这些值,因此,与其在prepare函数中缓存它们,不如在layoutAttributesForElementsInRect中实现一些逻辑以计算布局属性。在这种情况下,您可以使用可见矩形参数来仅计算将在屏幕上可见的单元格和视图的属性值。

    关于强制集合视图为所有返回的属性调用cellForItemAt,我不确定这样做的价值是什么,因为它将仅使用其中的几个。实现此目的的唯一方法是使用集合视图查看所显示内容的大小,以便所有单元格都被视为可见。但是,这样做将使使用集合视图的初衷变得无效,因为不会重复使用单元格并且它不会滚动。如果您要使用收藏夹视图项来修复一些奇怪的动画,那是不可行的。

    关于ios - UICollectionViewLayout.layoutAttributesForElementsInRect的行为,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59357522/

    10-10 21:01