滚动时集合视图单元格重复

Collection view cells duplicate when scrolling

我有一个集合视图,我有一个单元格的自定义 class。每个单元格都包含一个文本视图,这里是代码:

class CustomWriterPageCell: UICollectionViewCell, UITextViewDelegate {

    fileprivate let textViewOne: UITextView = {

        let tv = UITextView()
        tv.backgroundColor = .cyan
        tv.text = "Chapter Title"
        tv.font = UIFont(name: "Avenir-Roman", size: 27)
        tv.textColor = .gray
        return tv

    }()
}

这里是 cellForItemAt:

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "WriterPageCellID", for: indexPath) as! CustomWriterPageCell
    cell.backgroundColor = .clear

    return cell
}

文本视图有一个我通过以下代码实现的占位符(这是在自定义单元格中 class):

func textViewDidBeginEditing(_ textView: UITextView) {

    if textView.textColor == .gray {

        textView.text = nil
        textView.textColor = .black
    }
}

func textViewDidEndEditing(_ textView: UITextView) {

    if textView.text.isEmpty {
        textView.textColor = .gray
        textView.text = "Chapter Title"
    }
}

问题是,无论我在第一个单元格的文本视图中键入什么,都会出现在第四个单元格中,我知道这是因为 dequeueReusableCell 而发生的,但我似乎无法解决这个问题问题。

我假设第 4 个单元格不适合当前视图(即滚动下方可用 - 即重复使用的单元格)

1) 如果您要重复使用单元格,那么您需要确保在单元格离开视图之前,您需要将 UITextView 数据保存在某处。否则它会由于重用而丢失数据(即写入的文本)。以数据 structure/any 形式保存每个单元格的数据。

2) 如果滚动到第 4 个单元格,则检查数据是否存在。如果没有,则将空状态设置为文本视图。如果你写了一些东西然后以数据 structure/any 形式保存第 4 个单元格的数据.. (你可以用这个textViewDidEndEditing()保存当前数据)

3) 再次滚动回第一个单元格类型,那里有第一个单元格数据的保存数据 structure/any 形式的索引。

4) 现在滚动回第 4 个单元格。在重用期间,将第 4 个单元格的保存数据设置为单元格文本视图。

Data Saved at Index == Cell Index

确保正确处理用例。重用实现没有错。请确保您正确保存数据和重置数据。

问题是您没有指定在每个 CollectionViewCell 的 textView 上显示什么文本。只要您没有在 cellForItemAt indexPath 中指定相同的内容,它就会显示重复使用的单元格及其内容,如您所说,来自 dequeueReusableCell

对于您的特定问题的解决方案,您可以在 viewcontroller 中执行以下操作:

`var textViewContentArray = [Int: String]()` //Create a dictionary to hold the texts globally

textViewDidEndEditing:

func textViewDidEndEditing(_ textView: UITextView) {
    if textView.text.isEmpty {
        textView.textColor = .gray
        textView.text = "Chapter Title"
    } else {
        guard let cell = textView.superview?.superview as? CustomWriterPageCell else {
            return
        }
        guard  let indexPath = self.collectionView.indexPath(for: cell) else { return }
        textViewContentArray[indexPath.row] = textView.text
    }
}

textViewDidBeginEditing中:

func textViewDidBeginEditing(_ textView: UITextView) {
    textView.textColor = .black
}

并且在cellForItemAt indexPath:

override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CustomWriterPageCell", for: indexPath) as! CustomWriterPageCell
    cell.textView.delegate = self
    let text = textViewContentArray[indexPath.row]
    if !text.isEmpty {
        cell.textView.textColor = .black
        cell.textView.text = text
    } else {
        cell.textView.textColor = .gray
        cell.textView.text = "Chapter Title"
    }
    return cell
}

注意:这里我假设您已将保存 collectionView 的控制器设置为 textViewInCell 的委托,如果单元格是委托,您可以使用协议更新 textViewContentArray

希望这能增加您的理解。

我建议把你要改的部分封装成模型,比如你说的textColortext。不要手动更改UI显示,我的意思是通过修改模型然后刷新UI,这样就不会出现重复

这是所有表的规则,修改模型刷新UI,希望对你有用