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

时间:2019-09-20 17:39:06

标签: ios swift textview uicollectionview

我有一个集合视图,并且有一个用于单元格的自定义类。每个单元格都包含一个文本视图,下面是代码:

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
}

文本视图具有一个占位符,该占位符是通过以下代码实现的(位于自定义单元格类内部):

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而引起的,但我似乎无法解决此问题。

3 个答案:

答案 0 :(得分:2)

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

要解决特定问题,您可以在视图控制器中执行以下操作:

`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的委托的Controller,如果单元格是委托,则可以使用协议更新textViewContentArray

希望这可以加深您的理解。

答案 1 :(得分:0)

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

1)如果要重用单元格,则需要确保在单元格消失之前,您需要将UITextView数据保存在某个地方。否则它将因重复使用而丢失数据(即写入的文本)。以数据结构/任何形式保存每个单元格的数据。

2)如果滚动到第四个单元格,则检查是否存在数据。如果未设置,则将空状态设置为文本视图。如果您写东西,则以数据结构/任何形式保存第四个单元格的数据。 (您可以使用此textViewDidEndEditing()保存当前数据)

3)再次滚动回第一个单元格类型,其中有些存储了该索引的第一个单元格数据结构/任何形式的数据。

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

Data Saved at Index == Cell Index

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

答案 2 :(得分:0)

我建议将要更改的部分封装到模型中,例如您提到的textColortext。不要手动更改UI显示,我的意思是先修改模型,然后刷新UI,这样就不会重复。

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