dequeueReusableCell заставляет текст менять цвет - PullRequest
1 голос
/ 21 сентября 2019

У меня есть представление коллекции, и я использую пользовательский класс для ячеек.Каждая ячейка имеет два текстовых представления, 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: что бы я ни вводил в текстовом представлении впервая ячейка появляется в 4-й ячейке, чтобы решить эту проблему, мне нужно было создать 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, повторяющий проблему, чтобы помочь вам лучше понять, надеюсь, кто-то может помочь мневне, спасибо!:)

Video replicating the problem

Ответы [ 2 ]

1 голос
/ 21 сентября 2019

Следуя вашей цепочке вопросов, я предлагаю вам делать это каждый раз, когда вы имеете дело с UICollectionView или UITableView.

Определите метод в своем классе ячеек и возьмите любые данные, которые ему нужны, чтобы отобразить себя в качестве аргументов:

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.Хотя этот глобальный массив будет работать, я говорю о правильности кодирования.

Прокомментируйте ваши проблемы с этим подходом (если таковой имеется), я постараюсь ответить терпеливо, но не ожидаю (copy-paste) код в состоянии.

0 голосов
/ 21 сентября 2019

Это происходит из-за механизма повторного использования UICollectionView и UITableView.Поскольку вы обновляете цвет только одним способом, коллекция «запоминает» предыдущий цвет и при новой ячейке воссоздает его предыдущее состояние.У вас есть два основных решения:

Первый предназначен для обновления состояния ячейки для обоих случаев, например:

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

Второй предназначен для использования prepareForReuse метод UICollectionViewCell

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

Описание метода в Документация Apple

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...