【发布时间】:2016-07-23 01:29:23
【问题描述】:
小问题:
有没有办法在类似于insertItemsAtIndexPaths: deleteItemsAtIndexPaths: 甚至reloadItemsAtIndexPaths: 方法的performBatchUpdates: 块中添加和删除补充视图,如单元格和部分?
详细解释:
我使用带有部分的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];
}
}
}
}
}
如果所有数据从一开始就都可用并且数据没有变化,则此方法非常有用。但是,如果在生命周期内添加和删除数据,它就会惨遭失败。在performBatchUpdates: 中插入和删除单元格会弄乱补充视图。
会发生什么:
对于使用insertItemsAtIndexPaths: 插入的每个单元格,应删除同一indexPath 处的补充视图。此外,对于使用deleteItemsAtIndexPaths: 删除的每个单元格,应在同一indexPath 添加一个新的补充视图。
问题:
我的布局的prepareLayout: 被调用并计算正确的layoutAttributes。但是layoutAttributesForSupplementaryViewOfKind:atIndexPath: 被称为奇怪的indexPaths。具体来说,layoutAttributesForSupplementaryViewOfKind:atIndexPath: 被称为旧的 indexPaths,它已从 supplementaryViewAttributeList 数组中删除!
示例:
在插入新单元格的情况下,prepareLayout: 会正确删除layoutAttributes,但layoutAttributesForSupplementaryViewOfKind:atIndexPath: 仍会因不再可用且已删除的 indexPath 被调用!仅此而已。对于所有其他补充视图,无需额外调用任何其他indexPaths。
为什么 layoutAttributesForSupplementaryViewOfKind:atIndexPath: 调用 indexPaths 不再可用?如何正确删除、插入或重新加载补充视图?我错过了什么?
来源:
完整的源代码可以在这里找到:
CollectionView 控制器:
https://github.com/sarn/ARNClassicFilms/blob/master/classicFilms/classicFilms/view-controllers/ARNMovieOverviewController.m
(performBatchUpdates: 在类的最后一个方法中)
【问题讨论】:
-
嘿,我刚刚看到你的帖子,想知道你有没有发现什么?我遇到了very similar issue
-
上周我实际上在 WWDC 上询问了一位 Apple 工程师。他提供的解决方案是将
[[collectionView collectionViewLayout] invalidateLayout];添加到performBatchUpdates:块中。这实际上适用于我的情况。也许这对您的情况也有帮助 -
意味着我当时很接近,我在块之前添加了它,如果它有成果,我会尝试更新我的问题。
-
是的,我尝试添加它,但它仍然没有正确更新补充视图...one of the issues being this
标签: ios objective-c uicollectionview uicollectionviewlayout uicollectionreusableview