Элементы UITableView меняют цвет после прокрутки вниз, а затем обратно вверх Swift - PullRequest
3 голосов
/ 21 января 2020

Я создаю приложение iOS с swift и Xcode 11. Внутри моего приложения есть прокручиваемый контроллер табличного представления, состоящий из кнопок слева и справа, например:

enter image description here

Это 2 из множества UITableViewCells, которые я сделал. Когда пользователь нажимает красную кнопку, однажды красная кнопка становится зеленой. Но есть сбой: если я нажимаю красную кнопку (кнопка становится зеленой), а затем прокручиваю вниз внутри UITableView (и прокручиваю назад вверх), кнопка, которая когда-то была зеленой (и все еще должна быть зеленой), больше не зеленая. Я понятия не имею, почему это происходит, и я изучил другие подобные вопросы StackOverflow, как этот, но не смог найти ни одного.

Вот мой UITableViewController:

import UIKit

@objcMembers class CustomViewController: UITableViewController {

    var tag = 0

    override func viewDidLoad() {
        super.viewDidLoad()
        tag = 0
    }

    override func numberOfSections(in tableView: UITableView) -> Int {
        // #warning Incomplete implementation, return the number of sections
        tag = 0
        return 1
    }

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return SingletonViewController.themes.count
    }



    // 3
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        tag = tag + 1

        let cell = tableView.dequeueReusableCell(withIdentifier: "themeCell", for: indexPath) as! ThemeCell


            let cellButton = UIButton(frame: CGRect(x: 0, y: 5, width: 88, height: 119.5))
            cellButton.translatesAutoresizingMaskIntoConstraints = false
            cell.addSubview(cellButton)
            cell.accessoryView = cellButton
            cellButton.leadingAnchor.constraint(equalTo: cell.leadingAnchor, constant: 10).isActive = true
            cellButton.topAnchor.constraint(equalTo: cell.topAnchor, constant: 10).isActive = true
            cellButton.widthAnchor.constraint(equalToConstant: 88).isActive = true
            cellButton.heightAnchor.constraint(equalToConstant: 119.5).isActive = true
        cellButton.setImage(UIImage(named: SingletonViewController.themes[indexPath.row]), for: UIControl.State.normal)
            cellButton.addTarget(self, action: #selector(CustomViewController.backBTN(sender:)), for: .touchUpInside)
            cellButton.tag = tag

        var cellyi: UIButton!

//red/green button's declaration^
        cellyi = UIButton(frame: CGRect(x: 5, y: 5, width: 50, height: 30))
        cell.addSubview(cellyi)
        cell.accessoryView = cellyi
        cellyi.backgroundColor = UIColor.red
        cellyi.addTarget(self, action: #selector(CustomViewController.backBTN(sender:)), for: .touchUpInside)
        cellyi.tag = tag

        print(cellyi.tag)

        if UserDefaults.standard.integer(forKey: "like") == 0{
            UserDefaults.standard.set(1, forKey: "like")
        }

        if UserDefaults.standard.integer(forKey: "like") == tag{
            cellyi.backgroundColor = UIColor.green
        }

        tableView.allowsSelection = false
        return cell
    }

    @objc func backBTN(sender: UIButton){
        UserDefaults.standard.set(sender.tag, forKey: "like")

        tag = 0
        tableView.reloadData()
    }

}

1 Ответ

2 голосов
/ 21 января 2020

Метод cellForRowAt не предназначен для l oop!

Я вижу, что вы используете свойство tag для управления тем, что отображается в каждой ячейке. Из того факта, что вы увеличиваете tag само время вызова cellForRowAt, вы, похоже, предполагаете, что cellForRowAt будет вызываться один раз для каждой строки по порядку. Это не тот случай, и вам не следует реализовывать cellForRowAt следующим образом.

cellForRowAt по существу задает вопрос: «Какой должна быть ячейка на этом пути индекса?», и вы дадите ответ. Путь индекса, о котором запрашивается табличное представление, является параметром indexPath. Вы должны использовать этот параметр вместо вашего собственного свойства tag, потому что табличное представление не спрашивает об этом.

Причина, по которой ваш код не работает, заключается в том, что ячейки табличного представления используются повторно. Когда ячейки прокручиваются вне поля зрения, они не откладываются в сторону, поэтому, когда необходимо отобразить новые ячейки табличного представления, их можно перенастроить так, чтобы они «выглядели так, как будто они являются новыми ячейками». По сути, это означает, что при прокрутке вверх вызывается cellForRowAt для строк, которые вот-вот появятся. Вы не ожидали этого, не так ли?

Весь этот код, который устанавливает каждую ячейку, должен быть перемещен в инициализатор ThemeCell. Кроме того, дизайн ячейки в раскадровке. cellForRowAt должен настраивать ячейку только для пути индекса. ThemeCell должен иметь свойства cellButton и cellyi, чтобы к ним можно было получить доступ.

Теперь cellForRowAt можно записать так:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCell(withIdentifier: "themeCell", for: indexPath) as! ThemeCell

    cell.cellButton.setImage(UIImage(named: SingletonViewController.themes[indexPath.row]), for: UIControl.State.normal)
    cell.cellButton.addTarget(self, action: #selector(CustomViewController.backBTN(sender:)), for: .touchUpInside)

    cell.cellyi.addTarget(self, action: #selector(CustomViewController.backBTN(sender:)), for: .touchUpInside)

    if UserDefaults.standard.integer(forKey: "like") == indexPath.row {
        cell.cellyi.backgroundColor = UIColor.green
    } else {
        cell.cellyi.backgroundColor = UIColor.red
    }

    // this line should be moved to viewDidLoad
    // tableView.allowsSelection = false
    return cell
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...