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

Ios 如何正确插入或删除UICollectionView补充视图,ios,objective-c,uicollectionview,uicollectionviewlayout,uicollectionreusableview,Ios,Objective C,Uicollectionview,Uicollectionviewlayout,Uicollectionreusableview,简短问题: 是否有一种方法可以添加和删除类似于插入项扩展路径:删除项扩展路径:或甚至重新加载项扩展路径:方法的性能更新:块中的单元格和节等补充视图 详细解释: 我对节使用UICollectionView。这些单元像网格一样布置,每条线最多可以有6个单元。如果单元格的总数没有填满一个部分的所有行,我会添加额外的补充视图。附加的补充视图只是填补了空白。因此,结果应该是每个部分都被所有可用的单元完全填充,并且(可能)剩余的空白点被补充视图填充。因此,每行有6个视觉元素,即一个单元或一个补充视图 为了实

简短问题:

是否有一种方法可以添加和删除类似于
插入项扩展路径:
删除项扩展路径:
或甚至
重新加载项扩展路径:
方法的
性能更新:
块中的单元格和节等补充视图

详细解释:

我对节使用
UICollectionView
。这些单元像网格一样布置,每条线最多可以有6个单元。如果单元格的总数没有填满一个部分的所有行,我会添加额外的补充视图。附加的补充视图只是填补了空白。因此,结果应该是每个部分都被所有可用的单元完全填充,并且(可能)剩余的空白点被补充视图填充。因此,每行有6个视觉元素,即一个单元或一个补充视图

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

- (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];
                }
            }
        }
    }
}
-(无效)准备就绪{
[超级准备];
self.supplementaryViewAttributeList=[NSMutableArray];
if(self.collectionView!=nil){
//计算布局值
CGFloat contentWidth=self.collectionViewContentSize.width-self.sectionInset.left-self.sectionInset.right;
CGFloat cellSizeWithSpacing=self.itemSize.width+self.MinimumInTerminItemSpacing;
NSInteger numberOfItemsPerLine=楼层(内容宽度/单元大小与间距);
CGFloat realInterItemSpacing=(contentWidth-(numberOfItemsPerLine*self.itemSize.width))/(numberOfItemsPerLine-1);
//添加补充属性
对于(NSInteger numberOfSection=0;numberOfSection0&&NumberOfSupplementaryView<6){
NSIndexPath*indexPathOfLastCellOfSection=[NSIndexPath indexPathForItem:(numberOfItems-1)inSection:numberOfSection];
UICollectionViewLayoutAttributes*layoutAttributesOfLastCellOfSection=[ItemAtIndexPath:indexPathOfLastCellOfSection的自布局属性];
对于(NSInteger numberOfSupplementor=0;numberOfSupplementor
如果所有数据从一开始就可用,并且数据没有变化,则此操作非常有效。但是,如果数据在生命周期内被添加和删除,它将失败得很惨。在
性能更新:
中插入和删除单元格会弄乱补充视图

应该发生什么:

对于使用
insertitemsatindexpath插入的每个单元格:
应删除位于同一
indexPath
位置的补充视图。此外,对于使用
deleteeitemsatindexpath:
删除的每个单元格,应在同一
indexPath
处添加新的补充视图

问题:

调用我的布局的
prepareLayout:
,并计算正确的
layoutAttribute
。但是,对于怪异的
indexpath
调用了
layouttributesforSupplmentaryViewofKind:atIndexPath:
。具体地说,为从
补充视图属性列表
数组中删除的旧
索引路径
调用了
layouttributesforSupplmentaryViewofKind:atIndexPath:

示例:

在插入新单元格的情况下,
prepareLayout:
会正确删除
layouttributes
,但对于不再可用且已删除的indexPath,仍会调用
layouttributes for SupplementaryViewofKind:atIndexPath:
!只有这样。对于所有其他补充视图,不需要额外调用任何其他
indepath
s

为什么对不再可用的
indexpath
调用了种类为:aIndexPath:
的Supplmentary视图的
LayoutAttribute?如何正确删除、插入或重新加载补充视图?我错过了什么

来源:

完整来源可在此处找到:

自定义布局:

CollectionView控制器:
performBatchUpdates:
在类的最后一个方法中)

一个解决方案是向
performBatchUpdates:
块添加
[[collectionView collectionViewLayout]invalidateLayout]
。这会迫使布局重新计算并删除无效的索引路径。

你的评论对我来说并不是什么窍门,我找到了另一段代码并添加了它,它成功了,甚至删除了上面的建议,它仍然有效。有限公司
- (NSArray<NSIndexPath *>   *)indexPathsToDeleteForSupplementaryViewOfKind:(NSString *)elementKind
{
    return self.removedIndexPaths;
}