我很难理解prepareLayout
NSCollectionViewLayout
方法的目的。
根据官方的苹果文档,它是写的
在布局过程中,集合视图调用布局对象的多个方法来收集信息。特别是,它调用了三个非常重要的方法,其实现驱动核心布局行为。
使用 prepareLayout 方法执行初始布局计算。这些计算为布局对象以后执行的所有操作提供了基础。
使用 collectionViewContentSize 方法返回完全包围集合视图中所有元素的最小矩形。使用 prepareLayout 方法中的计算来指定此矩形。
使用 layoutAttributesForElementsInRect: 方法返回指定矩形中所有元素的布局属性。集合视图通常仅请求可见元素的子集,但可能包括屏幕外的元素。
prepareLayout 方法是执行与布局过程相关的主要计算的机会。使用此方法可为内容生成布局属性的初始列表。例如,使用此方法计算集合视图中所有元素的框架矩形。预先执行所有这些计算并缓存生成的数据通常比稍后尝试计算单个项目的属性更简单。
除了 layoutAttributesForElementsInRect: 方法之外,集合视图还可以调用其他方法来检索特定项的布局属性。通过提前执行计算,这些方法的实现应该能够返回缓存的信息,而无需先重新计算该信息。布局对象需要重新计算其布局信息的唯一时间是应用使布局无效。例如,当用户插入或删除项目时,您可能会使布局失效。
所以我天真地使用它作为指导,并重写了自定义布局的实现。我计算了collectionViewContentSize
并预先计算了此方法中使用的数组
- (NSArray<__kindof NSCollectionViewLayoutAttributes *>*)layoutAttributesForElementsInRect:(NSRect)rect;
这样在所有 3 个必需的方法中,我只返回缓存的值。在这之后,我的收藏视图突然变得非常滞后。
显然,每个卷轴上都会调用prepareLayout
方法。
谁能澄清这是什么意思。或者也许我什么都不懂?
如果您不希望每次出现滚动事件时都调用prepare
通常的事情是保留 CGSize 实例属性并实现shouldInvalidateLayout
以便仅当新边界大小与存储的 CGSize 属性值不同时才返回 YES。
这里有一个 Swift 的例子,但我相信你可以把它翻译成 Objective-C:
var oldBoundsSize = CGSize.zero
override func shouldInvalidateLayout(forBoundsChange newBounds: CGRect) -> Bool {
let ok = newBounds.size != self.oldBoundsSize
if ok {
self.oldBoundsSize = newBounds.size
}
return ok
}
所以这是我的错。显然,如果
- (BOOL)shouldInvalidateLayoutForBoundsChange:(NSRect)newBounds;
返回是。然后调用此方法。我刚刚更改了此方法返回 NO 并且一直调用的方法prepareLayout
已停止。