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 时将图像加载到错误的位置