我正在使用swift和Xcode 11制作一个iOS应用。在我的应用中,有一个可滚动的表格视图控制器,该控件由左右两侧的按钮组成,如下所示:
这些是我制作的许多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
应该具有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
}
关于ios - UITableView的项目向下滚动后更改颜色,然后快速备份,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/59836263/