我正在使用swift和Xcode 11制作一个iOS应用。在我的应用中,有一个可滚动的表格视图控制器,该控件由左右两侧的按钮组成,如下所示:

ios - UITableView的项目向下滚动后更改颜色,然后快速备份-LMLPHP

这些是我制作的许多UITableViewCells中的2个。当用户按下红色按钮时,曾经的红色按钮变为绿色。但是有一个小故障:如果我按下红色按钮(按钮变为绿色),然后在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()
    }

}

最佳答案

cellForRowAt方法不是for循环!

我看到您正在使用tag属性来控制每个单元格中显示的内容。从您在调用tag的同时就增加cellForRowAt的事实来看,您似乎假设对每一行依次按顺序调用cellForRowAt并非如此,您不应该像这样实现cellForRowAt
cellForRowAt本质上会问一个问题:“此索引路径上的单元格应该是什么?”,然后您提供答案。表视图询问的索引路径是indexPath参数。您应该使用此参数,而不要使用自己的tag属性,因为表视图并未对此进行询问。

您的代码无法正常工作的原因是因为表视图单元已被重用。当单元格滚动出视图时,它们不会放在一边,因此当需要显示新的表格视图单元格时,可以将它们重新配置为“看起来好像它们是新单元格”。本质上,这意味着当您向上滚动时,将为要显示的行调用cellForRowAt。您没想到的是吗?

设置每个单元格的所有代码都应移至ThemeCell的初始化程序。或者,在情节提要中设计单元格。 cellForRowAt应该只为索引路径专门配置一个单元格。 ThemeCell应该具有cellButtoncellyi属性,以便可以访问按钮。

现在,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
}

关于ios - UITableView的项目向下滚动后更改颜色,然后快速备份,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59836263/

10-11 01:21