使用 UICollectionView 和自定义流布局崩溃



我已经为集合视图实现了粘性部分标题,使用 http://blog.radi.ws/post/32905838158/sticky-headers-for-uicollectionview-using 作为起点,它们有效。

但我看到了一个非常奇怪的崩溃。

当我推送编辑器详细信息视图时,更改项目的名称,使其从一个部分移动到另一个部分(想想,更改联系人列表中按姓氏首字母分组的人的姓氏(,然后弹出回集合视图,它崩溃并提出投诉

UICollectionView received layout attributes for a cell with an index path that does not exist

以下是执行流程:

在编辑器详细信息视图中,我更改了项目的名称,使其从部分 X 移动到部分 Y。

物料的模型发出"名称已更改"通知。

拥有集合视图

的根视图控制器捕获"名称已更改"通知,重新生成其内部索引,然后在集合视图上调用 -reloadData。这一切都很好。

我点击了 UI 中的"后退"按钮,发生了以程(通过调试器和穴居人 NSlog 调用确认(

  • 被调用的节数,我的代码返回正确的节数
  • collectionView:NumberOfItemsInSection: 为每个部分调用,并返回正确的项目数
  • 我的自定义流布局的 -layoutAttributesForElementsInRect: 被调用。我在那里做的第一件事是调用[super layoutAttributesForElementsInRect]来获取基线布局。

记录继承的基线布局,我看到的是以前单元格排列的属性,而不是当前排列的属性。 例如,布局适用于我刚刚进行的编辑之前的排列。因此,不正确的部分和/或不正确部分中的单元格。

现在这就是让我大吃一惊的地方。

如果我注释掉 -layoutAttributesForElementsInRect 的整个实现,它仍然崩溃。但是,如果我评论掉:

- (BOOL) shouldInvalidateLayoutForBoundsChange:(CGRect)newBound {
    return YES;
}

然后,它正常工作。

这告诉我集合视图或流布局中的某些内容正在缓存结果,但前提是流布局应该无效布局边界更改

请注意,如果我只使用香草UICollectionViewFlowLayout,一切正常。

TLDR

自定义 UICollectionViewFlowLayout,如果 -shouldInvalidateLayoutForBoundsChange 返回 YES,则从 [super layoutAttributesForElementsInRect] 获取过期的布局属性

有什么想法吗?

我通过删除shouldInvalidateLayoutForBoundsChange:覆盖来解决此问题,而是在集合视图的委托上实现scrollViewDidScroll:以使布局无效:

override func scrollViewDidScroll(scrollView: UIScrollView) {
    collectionView?.collectionViewLayout.invalidateLayout()
}

这会保留粘性标头,但会阻止崩溃。

最新更新