-layoutAttributesForSupplementaryElementOfKind 没有 UICollectionViewLayoutAttributes 实例:

no UICollectionViewLayoutAttributes instance for -layoutAttributesForSupplementaryElementOfKind:

标题是我遇到的错误,我不知道为什么,但这里有一些信息,希望这里有人能解释我。

我已经对 UICollectionViewFlowLayout 进行了子类化,因为这样我就不用为 prepareLayout 中的单元格自己计算帧(也许这是个问题?)。然后我使用 UICollectionViewLayoutAttributes 信息来计算覆盖它的补充视图,我得到我想要的布局。

我使用 performBatchUpdates:completion: 添加、删除和更新视图。插入工作正常,但是删除项目时会出现标题中显示的错误。

所以我知道为什么会发生错误,但我不知道 为什么会发生错误。通过一个导致问题的场景的例子来澄清

  1. 从 1 个项目开始,1 个补充视图 1 个部分
  2. 再添加两个项目(prepareLayout 看到 3 个项目有 3 个补充视图)
  3. 删除项目(prepareLayout 看到 2 个视图和 2 个补充视图)
  4. layoutAttributesForSupplementaryViewOfKind:atIndexPath: 被调用要求索引路径的属性 section:0 和 item:2
  5. 崩溃是因为它要求第三个补充视图的属性,即使之前它调用准备布局设置 2 个项目和 2 个补充视图
  6. 无奈和绝望地举手

据我所知,有问题的函数是:

- (UICollectionViewLayoutAttributes *)layoutAttributesForSupplementaryViewOfKind:(NSString *)elementKind atIndexPath:(NSIndexPath *)indexPath
{
    return self.layoutInfo[elementKind][indexPath];
}

这当然是由 UICollectionView 的内部网络自动调用的,所以我不知道为什么它在那个索引路径上请求那个补充视图。

有人有什么想法吗?也许这就是我使用 performBatchUpdates:completion: 的方式,但在添加补充视图之前删除工作正常。我可以根据需要提供更多 code/explanation。

为了防止崩溃,您可以 return 为所有那些不再有效的 indexPaths 设置虚拟属性。像这样的东西可以帮助防止你的崩溃:

UICollectionViewLayoutAttributes *layoutAttributes = self.layoutInfo[elementKind][indexPath]; // add some safety checks if this access creates an out of bounds issue

// create dummy layoutAttributes
// the workaround
if (layoutAttributes == nil) {
    UICollectionViewLayoutAttributes *dummyLayoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:elementKind withIndexPath:indexPath];
    dummyLayoutAttributes.frame = CGRectZero;
    dummyLayoutAttributes.hidden = YES;
    layoutAttributes = dummyLayoutAttributes;
}

return layoutAttributes;

这仍然会导致视图堆栈中不应该存在的对象,但它们是隐藏的并且不会造成崩溃。下次 UICollectionView 更新其布局时,它应该清除旧的隐藏视图。

我在论坛上搜寻答案并找到了一些建议。 None 他们给了我需要的帮助,最终为了赶上最后期限,我完全放弃了补充意见。

几周后,出于好奇,我再次环顾四周,最终 came across the following post 现在我又回到了使用补充视图。

所以,别忘了return你的:

- (NSArray<NSIndexPath *> *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind
{
    return self.removedIndexPaths;
}

到您的 collection 视图布局。