从 UICollectionView 的一个部分中删除一行似乎不会删除关联的 header

Deleting a row from a section in UICollectionView doesn't seem to delete the associated header

我有自己的自定义 UICollectionViewLayout,它为给定部分中的每一行添加自定义 header,当我从该部分删除项目时,出现以下崩溃:

*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'no UICollectionViewLayoutAttributes instance for -layoutAttributesForSupplementaryElementOfKind: UICollectionElementKindSectionHeader at path {length = 2, path = 2 - 0}'

这对我来说毫无意义。我刚刚删除了 2 - 0 处的行,为什么它试图从我的布局 class 中请求 header?

这是我删除行的代码:

collectionView?.performBatchUpdates({
            self.trackControllers.remove(at: index)
            if self.collectionView?.numberOfItems(inSection: 2) > index {
                self.collectionView?.deleteItems(at: [IndexPath(row: index, section: 2)])
            }
        })

删除后该部分是否为空无关紧要,或者如果还有其他行,它似乎仍然为我刚刚删除的行请求header。

所以我设法自己解决了这个问题。

显然 UICollectionView 将继续请求相同的补充视图,直到删除动画结束。为了解决这个问题,我不得不覆盖 indexPathsToDeleteForSupplementaryView(ofKind elementKind: String) -> [IndexPath]。现在这愚蠢地没有向我们提供任何关于哪些 indexPaths 已被删除的信息,所以你必须自己在 prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem])

中跟踪这个

这是解决我的问题的代码:

fileprivate var deletedIndexPaths = [IndexPath]()
override func prepare(forCollectionViewUpdates updateItems: [UICollectionViewUpdateItem]) {
    deletedIndexPaths.removeAll()
    super.prepare(forCollectionViewUpdates: updateItems)

    let newlyDeletedItemsInSection2 = updateItems.filter({ [=10=].updateAction == .delete }).filter({ [=10=].indexPathBeforeUpdate?.section == 2 })
    let newlyDeletedIndexPaths = newlyDeletedItemsInSection2.flatMap({ [=10=].indexPathBeforeUpdate })
    deletedIndexPaths.append(contentsOf: newlyDeletedIndexPaths)
}

override func indexPathsToDeleteForSupplementaryView(ofKind elementKind: String) -> [IndexPath] {
    return deletedIndexPaths
}

override func finalizeCollectionViewUpdates() {
    deletedIndexPaths.removeAll()
}

(请注意,我只有 headers 的部分是第 2 部分)