dequeueReusableCell 导致文本改变颜色

dequeueReusableCell causes text to change color

我有一个集合视图,我正在为单元格使用自定义 class。每个单元格都有两个文本视图,chapterTitleTextView 和 chapterBodyTextView。我已将占位符添加到两个文本视图中,如下所示:

class CustomWriterPageCell: UICollectionViewCell, UITextViewDelegate {

    // When the user taps on a text view
    func textViewDidBeginEditing(_ textView: UITextView) {

        if textView.textColor == .gray {

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

    // When the user taps out of a text view or taps on the done button in the toolbar
    func textViewDidEndEditing(_ textView: UITextView) {

        // If the chapter title text view is empty
        if chapterTitleTextView.text.isEmpty {

            chapterTitleTextView.text = "Chapter Title"
            chapterTitleTextView.textColor = .gray

        }
        // If the chapter body text view is empty
        if chapterBodyTextView.text.isEmpty {

            chapterBodyTextView.text = "Chapter Body"
            chapterBodyTextView.textColor = .gray

        }
    }
}

这是如何工作的,文本颜色最初是灰色的,并且有一些文本,当用户点击文本视图时,颜色变为黑色,文本视图中的文本被删除。

现在使用 dequeueReusableCell 有这个问题,它重用了单元格,这导致了问题编号 1:无论我在第一个单元格的文本视图中键入什么,都出现在第四个单元格中,为了解决这个问题我有创建 2 个全局列表来保存我键入的任何内容,这将显示在单元格的文本视图中,代码如下:

全局列表:

var chapterTitleText = Array(repeating: "", count: 4) // To store the chapter title text
var chapterBodyText = Array(repeating: "", count: 4) // To store the chapter body text

以下代码片段位于之前的 textViewDidEndEditing 中

// Append the chapter body text to the chapterBodyText array
let titleText = chapterTitleTextView.text
let titleRow = textView.tag //This the indexPath.row
chapterTitleText[titleRow] = titleText!

// Append the chapter title text to the chapterTitleText array
let bodyText = chapterBodyTextView.text
let bodyRow = textView.tag
chapterBodyText[bodyRow] = bodyText!

并且在 cellForItemAt:

cell.chapterBodyTextView.tag = indexPath.row
cell.chapterTitleTextView.tag = indexPath.row

cell.chapterTitleTextView.text = chapterTitleText[indexPath.row]
cell.chapterBodyTextView.text = chapterBodyText[indexPath.row]

这解决了问题 1(文本视图中的文本重复)。但是后来我遇到了一个新问题,还记得我说的占位符文本吗?当我在第一个单元格的文本视图中键入内容时,第四个单元格中文本视图的文本颜色会发生变化。我将添加一个复制问题的 GIF 以帮助读者理解:

发生这种情况是因为 UICollectionViewUITableView 的重用机制。由于您仅以一种方式更新颜色,因此收集 "remembers" 以前的颜色并在新单元格上重新创建其以前的状态。这里有两个基本解决方案。

首先 是为两种情况更新细胞状态,如:

if myCondition == true {
  color = UIColor.gray
} else {
  color = UIColor.black
}

其次是利用UICollectionViewCell

prepareForReuse方法
func prepareForReuse() {
  // code that resets state of your cell to default 
}

Apple Documentation中的方法说明

根据你的问题链,我建议你每次处理 UICollectionViewUITableView 时都这样做。

在您的单元格中定义一个方法 class 并将其显示自身所需的任何数据作为参数:

func configure(text : String?) { //text is optional here which means it can be nil.
//However, from my previous answer you can replace it with an empty string condition.

    if let txt = text { //or if text != "" 
        self.chapterTitleTextView.text = txt
        self.chapterTitleTextView.text.textColor = .black
    }
    else {// As others mentioned make sure to always handle else because cells are reusable.
        self.chapterTitleTextView.text = "Chapter Title"
        self.chapterTitleTextView.text.textColor = .gray
    }

} 

可重用单元背后的直觉是,由于它们是可重用的,您应该完全重新配置它们,而不是期望配置被保存或附加到单元。

现在,在 cellForItemAt:

 let cell = ...
 cell.configure(text : chapterTitleText[indexPath.row])

请记住,通过这种方式,您无需定义全局数组。正如我之前告诉您的,这个数组只需要在您的控制器中定义,您的单元不需要知道它。您的单元格只需要知道通过 configure 函数传递的该数组的一个索引。 虽然那个全局数组可以工作,但我说的是编码的适当性。

用这种方法评论你的问题(如果有的话),我会尽量耐心回答,但不要指望(复制粘贴)代码。