如何正确插入或删除UICollectionView补充视图

简短的问题:

有没有一种方法来添加和删除类似于insertItemsAtIndexPaths: deleteItemsAtIndexPaths:或甚至reloadItemsAtIndexPaths:方法的performBatchUpdates:块中的单元格和部分的补充视图?

长解释:

我使用UICollectionView与部分。 单元格像网格一样布置,每行最多可以有6个单元格。 如果单元的总数不填满某个部分的所有行,我将添加其他补充视图。 额外的补充意见只是填补了空白。 所以结果应该是每个部分完全填充所有可用的单元格,并且(可能的)剩余空白点填充补充视图。 所以每行有6个视觉元素,一个单元格或一个补充视图。

为了实现这一点,我实现了一个自定义的UICollectionViewFlowLayout基于布局与以下prepareLayout:实现:

 - (void)prepareLayout { [super prepareLayout]; self.supplementaryViewAttributeList = [NSMutableArray array]; if(self.collectionView != nil) { // calculate layout values CGFloat contentWidth = self.collectionViewContentSize.width - self.sectionInset.left - self.sectionInset.right; CGFloat cellSizeWithSpacing = self.itemSize.width + self.minimumInteritemSpacing; NSInteger numberOfItemsPerLine = floor(contentWidth / cellSizeWithSpacing); CGFloat realInterItemSpacing = (contentWidth - (numberOfItemsPerLine * self.itemSize.width)) / (numberOfItemsPerLine - 1); // add supplementary attributes for (NSInteger numberOfSection = 0; numberOfSection < self.collectionView.numberOfSections; numberOfSection++) { NSInteger numberOfItems = [self.collectionView numberOfItemsInSection:numberOfSection]; NSInteger numberOfSupplementaryViews = numberOfItemsPerLine - (numberOfItems % numberOfItemsPerLine); if (numberOfSupplementaryViews > 0 && numberOfSupplementaryViews < 6) { NSIndexPath *indexPathOfLastCellOfSection = [NSIndexPath indexPathForItem:(numberOfItems - 1) inSection:numberOfSection]; UICollectionViewLayoutAttributes *layoutAttributesOfLastCellOfSection = [self layoutAttributesForItemAtIndexPath:indexPathOfLastCellOfSection]; for (NSInteger numberOfSupplementor = 0; numberOfSupplementor < numberOfSupplementaryViews; numberOfSupplementor++) { NSIndexPath *indexPathOfSupplementor = [NSIndexPath indexPathForItem:(numberOfItems + numberOfSupplementor) inSection:numberOfSection]; UICollectionViewLayoutAttributes *supplementaryLayoutAttributes = [UICollectionViewLayoutAttributes layoutAttributesForSupplementaryViewOfKind:ARNCollectionElementKindFocusGuide withIndexPath:indexPathOfSupplementor]; supplementaryLayoutAttributes.frame = CGRectMake(layoutAttributesOfLastCellOfSection.frame.origin.x + ((numberOfSupplementor + 1) * (self.itemSize.width + realInterItemSpacing)), layoutAttributesOfLastCellOfSection.frame.origin.y, self.itemSize.width, self.itemSize.height); supplementaryLayoutAttributes.zIndex = -1; [self.supplementaryViewAttributeList addObject:supplementaryLayoutAttributes]; } } } } } 

如果从一开始就可以获得所有的数据 ,并且数据没有变化,那么这种方法效果很好 。 但是,如果数据在生命周期中被添加和删除,那么它就会惨不忍睹。 在performBatchUpdates:插入和删除单元格: performBatchUpdates:补充视图。

应该发生什么:

对于使用insertItemsAtIndexPaths:插入的每个单元格insertItemsAtIndexPaths:应删除相同indexPath的补充视图。 此外,对于使用deleteItemsAtIndexPaths:删除的每个单元格,都应该在同一个indexPath处添加一个新的补充视图。

问题:

我的布局的prepareLayout:被调用并计算正确的layoutAttributes 。 但layoutAttributesForSupplementaryViewOfKind:atIndexPath:被称为奇怪的indexPaths 。 具体来说, layoutAttributesForSupplementaryViewOfKind:atIndexPath:将被从旧的indexPaths调用,这些旧的indexPaths已经从supplementaryViewAttributeList数组中移除!

例:

在插入新的单元格的情况下, prepareLayout:正确地删除了layoutAttributes ,但layoutAttributesForSupplementaryViewOfKind:atIndexPath: 仍然被调用为不再可用且已删除的indexPath ! 只为了。 对于所有其他补充视图,没有其他indexPath的额外调用。

为什么是layoutAttributesForSupplementaryViewOfKind:atIndexPath:调用indexPaths不再可用? 如何正确删除,插入或重新载入补充视图? 我错过了什么?

资源:

完整的源代码可以在这里find:

自定义布局: https : //github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/layout/ARNCollectionViewFocusGuideFlowLayout.m

CollectionView控制器: https : //github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/view-controllers/ARNMovieOverviewController.m ( performBatchUpdates:是在类的最后一个方法)

你的评论不是我做的伎俩,我发现了另一个代码,并添加它,它的工作,甚至删除了上述build议,它仍然工作。 收集意见肯定是强大的,但忘了一个function,如这一个…

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

事情可能会相当糟糕。

一种解决scheme是将一个[[collectionView collectionViewLayout] invalidateLayout]performBatchUpdates:块中。 这会强制布局重新计算并删除无效的indexPaths。