我试图了解UICollectionViewLayout
的工作原理,并找到了此示例代码。
https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
在示例代码(以及我可以找到的所有其他示例)中,它具有cachedLayoutAttributes
对象,并计算prepare()
中所有项目的布局。
我发现此模式有2个问题。
一种方法是,如果数据源的数量足够大,则在prepare()
方法中计算所有内容将花费时间(并且每当collectionView的布局更改时,它都会重新计算),因此看起来效率不高。 / p>
另一个问题是layoutAttributesForItem
或layoutAttributesForSupplementaryView
不会被调用。只有layoutAttributesForElements
被调用,似乎足以布置单元格/辅助视图。
我阅读了文档,但只说必须重写方法。我最好的猜测是,我应该使用重写这些方法来返回适当的UICollectionViewLayoutAttributes
并从layoutAttributesForElements
进行调用。但是,无论何时用户滚动UICollectionView都会调用此layoutAttributesForElements
,因此它似乎也不是很有效。
我想知道layoutAttributesForItem
和layoutAttributesForSupplementaryView
被调用的情况,以及如果UICollectionViewLayoutAttributes
的数目是多少,何时/何地/何处是计算UICollectionViewLayoutAttributes
的最佳方法/地点/时间数据源巨大。
更新
感谢您的评论。但是,这似乎是关于无效周期的优化。
旨在支持失效上下文的布局对象可以使用UICollectionViewLayoutInvalidationContext对象中的信息来优化失效周期中的行为。
这意味着UICollectionViewLayoutAttributes
已被设置并且仅使必要的部分无效,对吧?
那么,我应该在哪里第一次计算 <br>
<br>
<br>
<br>
<br>
<br>
?如果我错了,请告诉我。
答案 0 :(得分:1)
一种方法是,如果数据源的数量足够大,则在
prepare()
方法中计算所有内容将花费时间(并且每当collectionView的布局更改时,它都会重新计算),因此看起来效率不高。 / p>
是的,看起来效率不高。使prepare()
的计算尽可能高效是您的工作。
例如:仅计算一部分属性,并在使用shouldInvalidateLayout(forBoundsChange:)
滚动更改其位置时计算更多属性。但是请谨慎使用此方法,因为它可能会使每个像素滚动上的布局无效。
prepare()
方法不仅出于娱乐目的而调用,它还告诉您某些事情已更改,需要重新计算!但是有关更改的信息很难获得。您可以检查IGListKit在准备之前如何获取有关更改的信息:link。
首先调用另一个问题是
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
的更多信息。