为什么在向上和向下滚动时CollectionViewCell会发生故障?

时间:2018-10-18 14:21:37

标签: ios swift uicollectionview

问题

在我(以编程方式)创建的collectionView中上下滚动时,单元格似乎未正确出队。这导致其内容重复。

视频

Bug replication

恶意行为

我希望单元格正确出队,并且内容不会重复。

代码段

代码片段通过下面的Pastebin提供。我必须在SO上添加一些代码来满足markdown编辑器的要求。

open class CollectionDataSource<Provider: CollectionDataProviderProtocol, Cell: UICollectionViewCell>: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout where Cell: ConfigurableCell, Provider.T == Cell.T {

https://pastebin.com/CzHYxTDD

class ProductCell: UICollectionViewCell, ConfigurableCell {
}

https://pastebin.com/9Nkr3s4B

  

如果还有其他需要,请在评论中提出。

2 个答案:

答案 0 :(得分:2)

每次致电

func configure(_ item: ProductViewModel, at indexPath: IndexPath) {
    setupProductImage(with: item.productImage)
    setupStackView()
    setupProductLines(with: item.productLines)
}

您在productLineLabel = UILabel()内创建新实例setupProductLines()并将其添加到stackView

您应该更改此行为,或者更确切地说,使用prepareForReuse方法清除堆栈视图。

请记住,addArrangedSubview增加了suview的新添加元素的保留计数。如果使用 Debug View Hierarchy (调试视图层次结构)按钮(图1)停止执行应用程序,则很有可能会看到比单元格中期望的更多标签。

fig 1图1。

答案 1 :(得分:0)

问题

我每次打电话:

func configure(_ item: ProductViewModel, at indexPath: IndexPath) {
    setupProductImage(with: item.productImage)
    setupStackView()
    setupProductLines(with: item.productLines)
}

我创建了productLineLabel = UILabel()的新实例 因此,每次从cellForRowAtIndexPath调用configure(_ item :)时,它都会被复制。

解决方案

我使用了llb推荐的prepareForReuse来删除属于UIStackview类(包含UILabel)的子视图。我编写了以下扩展名,以减少繁琐的工作:

func addSubviews(with subviews: [UIView], in parent: UIView) {
    subviews.forEach { parent.addSubview($0) }
  }

实施

唯一要做的就是像下面这样从prepareForReuse调用自定义扩展函数:

  override func prepareForReuse() {
    let foundStackView = subviews.filter({$0.isKind(of: UIStackView.self)})[0] as? UIStackView
    guard let labels = foundStackView?.arrangedSubviews.filter({$0.isKind(of: UILabel.self)}) else { return }
    foundStackView?.removeArrangedSubviews(labels, shouldRemoveFromSuperview: true)
  }

信用额转到llb,请参阅下面的评论! <3谢谢。