Ios UICollectionView在滚动后不删除旧单元格
我有一个UICollectionView和一个网格图像。当你点击其中一个时,它会打开网格并显示一个子视图和一些细节。像这样: 我在UICollectionViewLayout中打开网格,方法是调整UICollectionViewLayoutAttribute并在transform3D属性上为选定项当前行下方的所有单元格设置转换。这真的很好,是一个更好的动画和一个更简单的方法,比我第一次尝试插入另一个单元格到网格,这是一个不同于其他单元格的大小 无论如何。。。它大部分时间都能工作,但在继续使用后,我会在“收藏”视图中看到旧图像。它们就像幽灵细胞。我不能点击它们,就像它们没有被正确地从集合视图中移除一样,它们坐在单元格的顶部,防止点击,只是一个麻烦。像这样: 知道为什么这些细胞会这样做吗 编辑: 我想补充一点,我认为只有当我快速滚动收藏视图时才会发生这种情况。我已经编写了自己的UICollectionViewFlowLayout替换来测试它是否仍然发生。是的 编辑2: 三维变换或布局与此无关。它一定是UICollectionView中的错误。我可以通过快速滚动来利用这个漏洞,让它停止,然后查询屏幕上的视图。通常有两倍数量的细胞,但它们是隐藏的,因为它们堆叠在一起。由于我所做的翻译,我上面的实现揭示了它们 这也会影响性能Ios UICollectionView在滚动后不删除旧单元格,ios,uicollectionview,Ios,Uicollectionview,我有一个UICollectionView和一个网格图像。当你点击其中一个时,它会打开网格并显示一个子视图和一些细节。像这样: 我在UICollectionViewLayout中打开网格,方法是调整UICollectionViewLayoutAttribute并在transform3D属性上为选定项当前行下方的所有单元格设置转换。这真的很好,是一个更好的动画和一个更简单的方法,比我第一次尝试插入另一个单元格到网格,这是一个不同于其他单元格的大小 无论如何。。。它大部分时间都能工作,但在继续使用后
请参阅我的答案以获得解决方案。我第二次编辑的问题详细说明了为什么会发生这种情况,下面是我的解决方法。它不是防弹的,但在我的情况下是有效的,如果您遇到类似的情况,您可以调整我的解决方案:
- (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];
}
及
对bandejapaisa的进一步评论是:仅在iOS 6下,我发现
UICollectionView
也有搞糟动画过渡的习惯。原始单元格将保留在原来的位置,复制副本,然后对副本进行动画处理。通常在原件上,但不总是这样。所以一个简单的边界测试是不够的
因此,我编写了一个自定义的UICollectionView
子类,它执行以下操作:
- (void)didAddSubview:(UIView *)subview
{
[super didAddSubview:subview];
//
// iOS 6 contains a bug whereby it fails to remove subviews, ever as far as I can make out.
// This is a workaround for that. So, if this is iOS 6...
//
if(![UIViewController instancesRespondToSelector:@selector(automaticallyAdjustsScrollViewInsets)])
{
// ... then we'll want to wait until visibleCells has definitely been updated ...
dispatch_async(dispatch_get_main_queue(),
^{
// ... then we'll manually remove anything that's a sub of UICollectionViewCell
// and isn't currently listed as a visible cell
NSArray *visibleCells = self.visibleCells;
for(UIView *view in self.subviews)
{
if([view isKindOfClass:[UICollectionViewCell class]] && ![visibleCells containsObject:view])
[view removeFromSuperview];
}
});
}
}
很明显,“这是iOS 6吗”测试不能再直接一点了,但它隐藏在我实际代码的一个类别中,这是一个遗憾。bandejapaisa答案的Swift UICollectionView扩展版本:
extension UICollectionView {
func removeNaughtyLingeringCells() {
// 1. Find the visible cells
let visibleCells = self.visibleCells()
//NSLog("We have %i visible cells", visibleCells.count)
// 2. Find the visible rect of the collection view on screen now
let visibleRect = CGRectOffset(bounds, contentOffset.x, contentOffset.y)
//NSLog("Rect %@", NSStringFromCGRect(visibleRect))
// 3. Find the subviews that shouldn't be there and remove them
//NSLog("We have %i subviews", subviews.count)
for aView in subviews {
if let aCollectionViewCell = aView as? UICollectionViewCell {
let origin = aView.frame.origin
if (CGRectContainsPoint(visibleRect, origin)) {
if (!visibleCells.contains(aCollectionViewCell)) {
aView.removeFromSuperview()
}
}
}
}
// 4. Refresh the collection view display
setNeedsDisplay()
}
}
你能发布一个截图吗?奇怪的随机时刻,几个小时前看到的。查看您的个人资料页面。有一个应用程序的想法。搜索Flickr API。在Github上看到FlickrKit。他认出了这个名字。英雄联盟网络概念!是的,我四处走动。。。。。你在利兹,我来自利兹。。。实际上,我正准备开车去那里。从未来的角度来看:我似乎在iOS 6下遇到了这个问题,但在iOS 7下却没有。当细胞在6岁以下通过动画移动时,它们通常会留下拷贝;滚动时,如果我在集合视图单元格的
removeFromSuperview
或集合视图的willRemoveSubview的创造性子类中添加代码以检查是否删除:
我看到视图从未被删除。在iOS 7下,我看不到这样的问题。所以我认为苹果已经修复了这个错误。根据到目前为止的评论,我觉得我还应该补充一句:我在约克住了五年,那时。你也应该看看这篇文章。我认为这是同样的事情,但更优雅的解决方案。我还没有完全测试过。非常感谢!在我的例子中,在相同的情况下删除隐藏的单元格效果很好。另外,我重现这个问题的方法是:1。滚动非常快。2.等待减速停止。3.删除单元格。4.等待删除动画完成。我在快速滚动调用performBatchUpdate:animations时看到了这种奇怪的“幽灵”效果,但我不知道它是什么。我永远不会想到collection视图正在为当前屏幕上的单元格创建一个新的单元格,这似乎适得其反。接得好,谢谢
extension UICollectionView {
func removeNaughtyLingeringCells() {
// 1. Find the visible cells
let visibleCells = self.visibleCells()
//NSLog("We have %i visible cells", visibleCells.count)
// 2. Find the visible rect of the collection view on screen now
let visibleRect = CGRectOffset(bounds, contentOffset.x, contentOffset.y)
//NSLog("Rect %@", NSStringFromCGRect(visibleRect))
// 3. Find the subviews that shouldn't be there and remove them
//NSLog("We have %i subviews", subviews.count)
for aView in subviews {
if let aCollectionViewCell = aView as? UICollectionViewCell {
let origin = aView.frame.origin
if (CGRectContainsPoint(visibleRect, origin)) {
if (!visibleCells.contains(aCollectionViewCell)) {
aView.removeFromSuperview()
}
}
}
}
// 4. Refresh the collection view display
setNeedsDisplay()
}
}