使用缓存的UICollectionViewLayoutAttributes子类化UICollectionViewLayout

时间:2019-05-31 22:44:05

标签: ios swift uicollectionview uicollectionviewlayout

我试图了解UICollectionViewLayout的工作原理,并找到了此示例代码。

https://developer.apple.com/documentation/uikit/uicollectionview/customizing_collection_view_layouts

在示例代码(以及我可以找到的所有其他示例)中,它具有cachedLayoutAttributes对象,并计算prepare()中所有项目的布局。

我发现此模式有2个问题。

一种方法是,如果数据源的数量足够大,则在prepare()方法中计算所有内容将花费时间(并且每当collectionView的布局更改时,它都会重新计算),因此看起来效率不高。 / p>

另一个问题是layoutAttributesForItemlayoutAttributesForSupplementaryView不会被调用。只有layoutAttributesForElements被调用,似乎足以布置单元格/辅助视图。

我阅读了文档,但只说必须重写方法。我最好的猜测是,我应该使用重写这些方法来返回适当的UICollectionViewLayoutAttributes并从layoutAttributesForElements进行调用。但是,无论何时用户滚动UICollectionView都会调用此layoutAttributesForElements,因此它似乎也不是很有效。

我想知道layoutAttributesForItemlayoutAttributesForSupplementaryView被调用的情况,以及如果UICollectionViewLayoutAttributes的数目是多少,何时/何地/何处是计算UICollectionViewLayoutAttributes的最佳方法/地点/时间数据源巨大。

更新

感谢您的评论。但是,这似乎是关于无效周期的优化。

  

旨在支持失效上下文的布局对象可以使用UICollectionViewLayoutInvalidationContext对象中的信息来优化失效周期中的行为。

这意味着UICollectionViewLayoutAttributes已被设置并且仅使必要的部分无效,对吧?

那么,我应该在哪里第一次计算 <br> <br> <br> <br> <br> <br> ?如果我错了,请告诉我。

1 个答案:

答案 0 :(得分:1)

  

一种方法是,如果数据源的数量足够大,则在prepare()方法中计算所有内容将花费时间(并且每当collectionView的布局更改时,它都会重新计算),因此看起来效率不高。 / p>

是的,看起来效率不高。使prepare()的计算尽可能高效是您的工作。

例如:仅计算一部分属性,并在使用shouldInvalidateLayout(forBoundsChange:)滚动更改其位置时计算更多属性。但是请谨慎使用此方法,因为它可能会使每个像素滚动上的布局无效。

prepare()方法不仅出于娱乐目的而调用,它还告诉您某些事情已更改,需要重新计算!但是有关更改的信息很难获得。您可以检查IGListKit在准备之前如何获取有关更改的信息:link

  

另一个问题是layoutAttributesForItemlayoutAttributesForSupplementaryView不会被调用。只有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的更多信息。