使用缓存的 UICollectionViewLayoutAttributes 子类化 UICollectionViewLayout
Subclassing UICollectionViewLayout with cached UICollectionViewLayoutAttributes
我试图了解 UICollectionViewLayout
的工作原理并找到了这个示例代码。
https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
在示例代码(以及我能找到的所有其他示例)中,它有 cachedLayoutAttributes
对象并计算 prepare()
中所有项目的布局。
我发现此模式有 2 个问题。
一个是如果数据源的数量足够大,prepare()
方法中的所有东西都计算起来会比较费时间(而且collectionView的layout一有变化就会重新计算),所以看起来效率不是很高.
另一个问题是 layoutAttributesForItem
或 layoutAttributesForSupplementaryView
没有机会被调用。仅 layoutAttributesForElements
被调用,似乎足以布局 cells/supplementary 视图。
我阅读了文档,但它只说必须覆盖这些方法。我最好的猜测是我应该使用将这些方法覆盖到 return 一个合适的 UICollectionViewLayoutAttributes
并从 layoutAttributesForElements
调用它们。然而,只要用户滚动 UICollectionView,这个 layoutAttributesForElements
就会被调用,所以它似乎也不是很有效。
我想知道是什么情况 layoutAttributesForItem
和 layoutAttributesForSupplementaryView
被调用,what/when/where 是最好的 way/place/time 来计算 UICollectionViewLayoutAttributes
如果数据源数量庞大。
更新
感谢您的评论。不过好像是关于失效周期的优化。
Layout objects that are designed to support invalidation contexts can use the information in a UICollectionViewLayoutInvalidationContext object to optimize their behavior during the invalidation cycle.
这意味着 UICollectionViewLayoutAttributes
已经设置并且只使必要的部分无效,对吗?
那么,第一次计算UICollectionViewLayoutAttributes
应该在哪里呢?如果我错了,请告诉我。
One is if the number of data source is big enough, calculating everything in the prepare()
method will take time(and it will be recalculated whenever collectionView's layout changes), so it doesn't look very efficient.
是的,看起来效率不高。让 prepare()
计算尽可能高效是你的工作。
例如:只计算一部分属性,使用shouldInvalidateLayout(forBoundsChange:)
滚动改变位置时计算更多属性。但要小心使用此方法,因为它可能会使每个像素滚动上的布局无效。
prepare()
方法不是为了好玩而调用的,它通知您某些内容已更改,需要重新计算!但是有关更改的信息很难获得。您可以查看 IGListKit gets information about changes before prepare: link.
The other issue is that there is no chance layoutAttributesForItem
or layoutAttributesForSupplementaryView
get called. Only layoutAttributesForElements
gets called and it seems it is sufficient enough to layout cells/supplementary views.
layoutAttributesForElements(in:)
首先被调用,因为该集合不知道您的单元格和补充视图的顺序。所以它要求指定矩形中的所有属性。试试insert/move/delete/reload格,我相信layoutAttributesForItem(at:)
可能会被调用。或者可能不是。但是你不必担心,因为你已经有了属性缓存。
既然你缓存了属性 layoutAttributesForElements(in:)
应该足够有效并且看起来像这样:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributes
.reduce(into: [UICollectionViewLayoutAttributes](), { [=10=] += .filter({ [=10=].frame.intersects(rect) }) })
}
我个人建议看一些难点的open-source布局。与来自任何简单示例项目的信息相比,您将获得更多关于 UICollectionViewLayout
的信息。
我试图了解 UICollectionViewLayout
的工作原理并找到了这个示例代码。
https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts
在示例代码(以及我能找到的所有其他示例)中,它有 cachedLayoutAttributes
对象并计算 prepare()
中所有项目的布局。
我发现此模式有 2 个问题。
一个是如果数据源的数量足够大,prepare()
方法中的所有东西都计算起来会比较费时间(而且collectionView的layout一有变化就会重新计算),所以看起来效率不是很高.
另一个问题是 layoutAttributesForItem
或 layoutAttributesForSupplementaryView
没有机会被调用。仅 layoutAttributesForElements
被调用,似乎足以布局 cells/supplementary 视图。
我阅读了文档,但它只说必须覆盖这些方法。我最好的猜测是我应该使用将这些方法覆盖到 return 一个合适的 UICollectionViewLayoutAttributes
并从 layoutAttributesForElements
调用它们。然而,只要用户滚动 UICollectionView,这个 layoutAttributesForElements
就会被调用,所以它似乎也不是很有效。
我想知道是什么情况 layoutAttributesForItem
和 layoutAttributesForSupplementaryView
被调用,what/when/where 是最好的 way/place/time 来计算 UICollectionViewLayoutAttributes
如果数据源数量庞大。
更新
感谢您的评论。不过好像是关于失效周期的优化。
Layout objects that are designed to support invalidation contexts can use the information in a UICollectionViewLayoutInvalidationContext object to optimize their behavior during the invalidation cycle.
这意味着 UICollectionViewLayoutAttributes
已经设置并且只使必要的部分无效,对吗?
那么,第一次计算UICollectionViewLayoutAttributes
应该在哪里呢?如果我错了,请告诉我。
One is if the number of data source is big enough, calculating everything in the
prepare()
method will take time(and it will be recalculated whenever collectionView's layout changes), so it doesn't look very efficient.
是的,看起来效率不高。让 prepare()
计算尽可能高效是你的工作。
例如:只计算一部分属性,使用shouldInvalidateLayout(forBoundsChange:)
滚动改变位置时计算更多属性。但要小心使用此方法,因为它可能会使每个像素滚动上的布局无效。
prepare()
方法不是为了好玩而调用的,它通知您某些内容已更改,需要重新计算!但是有关更改的信息很难获得。您可以查看 IGListKit gets information about changes before prepare: link.
The other issue is that there is no chance
layoutAttributesForItem
orlayoutAttributesForSupplementaryView
get called. OnlylayoutAttributesForElements
gets called and it seems it is sufficient enough to layout cells/supplementary views.
layoutAttributesForElements(in:)
首先被调用,因为该集合不知道您的单元格和补充视图的顺序。所以它要求指定矩形中的所有属性。试试insert/move/delete/reload格,我相信layoutAttributesForItem(at:)
可能会被调用。或者可能不是。但是你不必担心,因为你已经有了属性缓存。
既然你缓存了属性 layoutAttributesForElements(in:)
应该足够有效并且看起来像这样:
override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
return attributes
.reduce(into: [UICollectionViewLayoutAttributes](), { [=10=] += .filter({ [=10=].frame.intersects(rect) }) })
}
我个人建议看一些难点的open-source布局。与来自任何简单示例项目的信息相比,您将获得更多关于 UICollectionViewLayout
的信息。