UICollectionView 在滚动后显示错误的单元格 - 出队问题?

Posted

技术标签:

【中文标题】UICollectionView 在滚动后显示错误的单元格 - 出队问题?【英文标题】:UICollectionView showing wrong cells after scrolling - dequeue issue? 【发布时间】:2012-10-31 17:47:50 【问题描述】:

我在 UIViewController 中有一个 UICollectionView。在 collectionView cellForItemAtIndexPath: 方法中,它根据数据源创建一系列自定义单元格。自定义单元格依次包含 UIView,子类化以绘制单个 PDF 页面。

它的设置方式是将 PDF 文件拆分为单个页面,因此单元格 1 包含 PDF 页面 1,单元格 2 包含 PDF 页面 2,依此类推。到目前为止一切顺利,这是我的问题:

当我向下滚动时,UICollectionView 开始显示错误的单元格。例如,在一个 34 页的文档中,它以正确的顺序显示单元格/第 1-16 页,但随后开始显示 似乎 已进一步向上出列的页面,例如单元格 1、单元格 2、单元格 4。我从来没有靠近单元格/第 34 页。

我过去曾在 UITableView 中看到过类似的行为,并且认为这与单元格的出列或委托方法有关。不太确定 - 任何帮助表示赞赏。

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath 

//create custom cell
CustomCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"cellID" forIndexPath:indexPath];

//set file name (always the same; one PDF file)
cell.fileName = fileName;
cell.backgroundColor = [UIColor clearColor];

//set the title to the page number
cell.title = [NSString stringWithFormat:@"page %@", [countArray objectAtIndex:indexPath.row]];

//set the current page (which indicates which page to display) according to the pageCount
cell.currentPage = [[countArray objectAtIndex:indexPath.row] intValue];

return cell; 

【问题讨论】:

也许我也有同样的问题。你找到解决办法了吗? 【参考方案1】:

我遇到过类似的问题。这很可能是因为重用的单元格不会自己重绘。在您的自定义单元格的 content 类(您的 PDF 视图)中,如果框架更新,则触发重绘:

-(void)setFrame:(CGRect)frame 
    [super setFrame:frame];
    [self setNeedsDisplay]; // force drawRect:

这对我有用。此外,如果您的单元格大小可能会发生变化,请设置自动调整大小掩码,使其填充空间

self.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;

在初始化期间。

【讨论】:

这对我有用 - 谢谢你的帮助。从 UICollectionView 的 cellForItemAtIndexPath 内部调用上面的 setFrame 方法,强制 PDF 重绘。非常感谢。 太棒了!可能没有必要自己调用setFrame:,因为无论如何集合视图都会这样做。 设置调整大小掩码有帮助, 我听从了 Chris 的建议,但实际上我需要在设置单元格之后和返回之前在单元格上调用 setNeedsDisplay【参考方案2】:

使用 prepareForReuse 方法修复了类似问题

只需将此方法添加到您的自定义单元实现中

- (void)prepareForReuse 

     self.fileName = nil;
     self.title = nil;

     // add remaining properties 


【讨论】:

@PuneethKamath 你不需要调用这个方法,只需在你的 UICollectionViewCell 子类中添加这个【参考方案3】:

我根据 Asatur Galstyan 的回答迅速修复了一个类似的问题。

将自定义类关联到情节提要中的单元格后,可以重写 prepareForReuse() 函数:

import UIKit

class SomeCollectionViewCell: UICollectionViewCell 

    @IBOutlet weak var exampleView: UIView!
    @IBOutlet weak var exampleLabel: UILabel!

    override func prepareForReuse()
        super.prepareForReuse()
        exampleLabel.textColor = nil
        exampleView.backgroundColor = nil
        exampleView.layer.cornerRadius = 0
    

prepareForReuse() 的默认实现除了Apple recommends calling the the super.prepareForReuse() when overriding anyway 之外什么都不做(至少在 ios 10 中)。

【讨论】:

根据您的示例,我发现prepareForReuse() 中的exampleView.setNeedsDisplay() 解决了这个问题。

以上是关于UICollectionView 在滚动后显示错误的单元格 - 出队问题?的主要内容,如果未能解决你的问题,请参考以下文章

当异步添加新项目时,UICollectionView 快速滚动在单元格中显示错误的图像

UICollectionView 在滚动时重新加载错误的图像

iOS 10 GM 嵌入 UITableView 和 UICollectionView contentSize 错误且滚动指示器不显示

UICollectionView 在滚动 Alamofire 时将图像加载到错误的位置

自定义 UIView 添加到视图后 UICollectionView 不滚动

在 UICollectionView 中滚动 2-3 次后单元格消失