UICollectionView滚动后不删除旧单元格

ban*_*isa 14 ios uicollectionview

我有一个带有图像网格的UICollectionView.当您点击其中一个时,它会打开网格并显示包含一些详细信息的子视图.像这样:

假设看起来像这样

我通过调整UICollectionViewLayoutAttributes并在transform3D属性上为所选项目的当前行下面的所有单元格设置转换,在我的UICollectionViewLayout中打开网格.这非常好用,并且是比我第一次尝试将另一个单元格插入网格时更好的动画和更简单的方法,该网格与其他单元格的大小不同.

无论如何......它大部分时间都有效,但在继续使用之后我会在集合视图中看到旧图像.它们就像幽灵细胞.我无法点击它们,就像它们没有被正确地从集合视图中移除一样,并且它们位于单元顶部以防止点击并且只是令人讨厌.像这样:

问题看起来像这样

任何想法为什么这些细胞这样做?

编辑:我想补充一下,我认为只有当我快速滚动集合视图时才会发生这种情况.我已经编写了自己的UICollectionViewFlowLayout替换来测试它是否仍然存在.确实如此.

编辑2:3D变换或布局与此无关.它必须是UICollectionView中的错误.我可以通过快速滚动,让停止,然后查询屏幕上的视图来利用.细胞数量通常是两倍,但它们在彼此堆叠时是隐藏的.我上面的实现揭示了它们,因为我做了翻译.

这确实会损害性能.

请参阅我的答案以获得解决方案

ban*_*isa 14

我对我的问题的第二次编辑详细说明了为什么会发生这种情况,这是我的解决方法.这不是防弹,但它适用于我的情况,如果你遇到类似的东西,你可以调整我的解决方案:

- (void) removeNaughtyLingeringCells {

    // 1. Find the visible cells
    NSArray *visibleCells = self.collectionView.visibleCells;
    //NSLog(@"We have %i visible cells", visibleCells.count);

    // 2. Find the visible rect of the collection view on screen now
    CGRect visibleRect;
    visibleRect.origin = self.collectionView.contentOffset;
    visibleRect.size = self.collectionView.bounds.size;
    //NSLog(@"Rect %@", NSStringFromCGRect(visibleRect));


    // 3. Find the subviews that shouldn't be there and remove them
    //NSLog(@"We have %i subviews", self.collectionView.subviews.count);
    for (UIView *aView in [self.collectionView subviews]) {
        if ([aView isKindOfClass:UICollectionViewCell.class]) {
            CGPoint origin = aView.frame.origin;
            if(CGRectContainsPoint(visibleRect, origin)) {
                if (![visibleCells containsObject:aView]) {
                    [aView removeFromSuperview];
                }
            }
        }
    }
    //NSLog(@"%i views shouldn't be there", viewsShouldntBeThere.count);

    // 4. Refresh the collection view display
    [self.collectionView setNeedsDisplay];    
}
Run Code Online (Sandbox Code Playgroud)

- (void) scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate {
    if (!decelerate) {
        [self removeNaughtyLingeringCells];
    }
}

- (void) scrollViewDidEndDecelerating:(UIScrollView *)scrollView {
    [self removeNaughtyLingeringCells];
}
Run Code Online (Sandbox Code Playgroud)