从UICollectionView中的节删除行似乎不会删除关联的标头

时间:2016-12-06 14:48:03

标签: ios swift header uicollectionview uicollectionviewlayout

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

  

***由于未捕获的异常'NSInternalInconsistencyException'而终止应用程序,原因:'没有UICollectionViewLayoutAttributes实例用于-layoutAttributesForSupplementaryElementOfKind:路径中的UICollectionElementKindSectionHeader {length = 2,path = 2 - 0}'

这对我没有意义。我刚刚删除了2 - 0的行,为什么它试图从我的布局类中请求一个标题?

这是删除行的代码:

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

如果删除后该部分为空,或者还有其他行,则它似乎仍然请求我刚刚删除的行的标题。

1 个答案:

答案 0 :(得分:4)

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

显然,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({ $0.updateAction == .delete }).filter({ $0.indexPathBeforeUpdate?.section == 2 })
    let newlyDeletedIndexPaths = newlyDeletedItemsInSection2.flatMap({ $0.indexPathBeforeUpdate })
    deletedIndexPaths.append(contentsOf: newlyDeletedIndexPaths)
}

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

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

(请注意,我唯一拥有标题的部分是第2部分)