我已经实现了来自UICollectionViewLayout的集合视图布局子类。在prepare中,我计算和缓存布局属性。在layoutAttributesForElementsInRect中,我过滤掉那些不符合rect的内容:
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方法仍然只对可见rect中的属性调用。
是预期的行为吗?如果是,那么在我的代码中筛选属性的目的是什么,如果集合视图本身是这样的话?我没有发现任何性能问题。
是否可以强制集合视图为所有返回的属性调用cellForItemAt?
发布于 2019-12-20 03:16:34
是的,这是集合视图的预期行为。在UICollectionViewLayout的文档中,苹果说:
布局对象的工作是确定单元格、补充视图和装饰视图的位置--在集合视图的边界中,并在询问时向集合视图报告该信息。
然后继续说:
集合视图要求其布局对象在许多不同的时间为这些元素提供布局信息。显示在屏幕上的每个单元格和视图都是使用来自布局对象的信息定位的。
在您的代码中筛选属性的目的是提高性能。主要有三个因素影响布局对象的性能:
attributes.
在上述条件不友好的情况下(您有很多项,计算属性非常复杂,而且您的自定义属性需要大量内存),提前计算所有属性是不可行的,因为预计算这些值需要花费大量的时间和资源,因此,与其在prepare函数中缓存它们,不如在layoutAttributesForElementsInRect中实现一些逻辑来计算布局属性。在这种情况下,您只使用可见的rect param来计算单元格和视图的属性值,这些属性在屏幕上是可见的。
关于强制集合视图对所有返回的属性调用cellForItemAt,我不确定这样做的价值是什么,因为它将只使用其中的几个属性。实现这一目标的唯一方法是拥有一个与您正在显示的内容大小相同的集合视图,以便所有单元格都被认为是可见的。但是,这样做会使使用集合视图的意义一开始就无效,因为单元格不会被重用,也不会滚动。如果您想用集合视图项来修复一些奇怪的动画,这并不是正确的方法。
https://stackoverflow.com/questions/59357522
复制相似问题