UITableView自定义单元格按钮从主视图中选择其他按钮?
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了UITableView自定义单元格按钮从主视图中选择其他按钮?相关的知识,希望对你有一定的参考价值。
在我的自定义tableviewcell上,我有一个按钮,用户可以按下该按钮在选中和未选中之间切换。这只是一个简单的UIButton,这个按钮包含在我的customtableviewcell中作为插座。
import UIKit
class CustomCellAssessment: UITableViewCell {
@IBOutlet weak var name: UILabel!
@IBOutlet weak var dateTaken: UILabel!
@IBOutlet weak var id: UILabel!
@IBOutlet weak var score: UILabel!
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
@IBAction func selectButton(_ sender: UIButton) {
if sender.isSelected{
sender.isSelected = false
}else{
sender.isSelected = true
}
}
}
奇怪的是,当我按下第一个单元格上的按钮时,它会在同一个tableview中的另一个单元格(在视图外)上选择一个按钮8个单元格。每个单元格都有自己的按钮,但就好像使用dequeReusableCell会导致系统以这种方式运行。它为什么这样做,是否与UIbuttons在tableviewcells上的工作方式有关?
谢谢
每个单元格都有自己的按钮,但就好像使用dequeReusableCell会导致系统以这种方式运行。
错误。 UITableViewCells是可重用的,因此如果你的tableView有8个单元格可见,当加载第9个时,单元格nr 1将被重用。
解决方案:您需要跟踪细胞的状态。调用cellForRowAtIndexPath
方法时,需要从头开始配置单元格。
您可以在ViewController中包含一个包含单元格状态的小数组:
var cellsState: [CellState]
并为每个indexPath存储选定的状态。然后在cellForRowAtIndexPath中,配置具有状态的单元格。
cell.selected = self.cellsState[indexPath.row].selected
所以,我要做的概述是:
1 - 在cellForRowAtIndexPath
,我会设置
cell.button.tag = indexPath.row
cell.selected = cellsState[indexPath.row].selected
2 - 将IBAction移动到ViewController或TableViewController
3 - 调用click方法时,更新单元格的选定状态
self.cellsState[sender.tag].selected = true
请记住始终在cellForRowAtIndexPath
配置整个单元格
编辑:
import UIKit
struct CellState {
var selected:Bool
init(){
selected = false
}
}
class MyCell: UITableViewCell {
@IBOutlet weak var button: UIButton!
override func awakeFromNib() {
self.button.setTitleColor(.red, for: .selected)
self.button.setTitleColor(.black, for: .normal)
}
}
class ViewController: UIViewController, UITableViewDataSource {
var cellsState:[CellState] = []
@IBOutlet weak var tableView: UITableView!
override func viewDidLoad() {
super.viewDidLoad()
//Add state for 5 cells.
for _ in 0...5 {
self.cellsState.append(CellState())
}
}
@IBAction func didClick(_ sender: UIButton) {
self.cellsState[sender.tag].selected = true
self.tableView.reloadData()
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellsState.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! MyCell
cell.button.isSelected = self.cellsState[indexPath.row].selected
cell.button.tag = indexPath.row
return cell
}
}
点击按钮时,您将设置按钮的选定状态。当单元格被重用时,按钮仍处于选中状态 - 您没有做任何事情来重置或更新该状态。
如果按钮选择与表格单元格选择分开,则需要跟踪所选按钮的索引路径作为数据模型的一部分,然后更新tableView(_: cellForRowAt:)
中按钮的选定状态。
表视图将只创建所需数量的单元格,以显示一个屏幕和一位信息。之后,细胞被重复使用。如果一个单元格从屏幕顶部滚动,表格视图将其置于重用队列中,然后当您需要在滚动时在底部显示一个新行时,它会将其拉出队列并将其提供给您tableView(_: cellForRowAt:)
。
您在此处获得的单元格与之前使用8行左右的单元格完全相同,您可以完全配置它。您可以在cellForRow
中执行此操作,并且您还可以通过实现prepareForReuse
在单元格本身中获得机会,tableView(_: cellForRowAt:)
在单元格出列之前调用。
在你的cell.button.addTarget(self, action: #selector(self.selectedButton), for: .touchUpInside)
中点击按钮并添加目标
indexPath
在目标方法使用下面的行来获得func selectedButton(sender: UIButton){
let hitPoint: CGPoint = sender.convert(CGPoint.zero, to: self.tableView)
let indexPath: NSIndexPath = self.tableView.indexPathForRow(at: hitPoint)! as NSIndexPath
}
indexPath
然后使用那个indexPath
做你的东西。实际上你的方法找不到点击哪个1. First create a protocol to know when button is clicked
按钮,这就是为什么不使用你想要的按钮。
解决问题的一种方法如下
protocol MyCellDelegate: class {
func cellButtonClicked(_ indexPath: IndexPath)
}
2. Now in your cell class, you could do something like following
class MyCell: UITableViewCell {
var indexPath: IndexPath?
weak var cellButtonDelegate: MyCellDelegate?
func configureCell(with value: String, atIndexPath indexPath: IndexPath, selected: [IndexPath]) {
self.indexPath = indexPath //set the indexPath
self.textLabel?.text = value
if selected.contains(indexPath) {
//this one is selected so do the stuff
//here we will chnage only the background color
backgroundColor = .red
self.textLabel?.textColor = .white
} else {
//unselected
backgroundColor = .white
self.textLabel?.textColor = .red
}
}
@IBAction func buttonClicked(_ sender: UIButton) {
guard let delegate = cellButtonDelegate, let indexPath = indexPath else { return }
delegate.cellButtonClicked(indexPath)
}
}
3. Now in your controller. I'm using UItableViewController here
class TheTableViewController: UITableViewController, MyCellDelegate {
let cellData = ["cell1","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4","cell2","cell3","cell4"]
var selectedIndexpaths = [IndexPath]()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(MyCell.self, forCellReuseIdentifier: "MyCell")
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return cellData.count
}
override func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return 55.0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyCell", for: indexPath) as! MyCell
cell.cellButtonDelegate = self
cell.configureCell(with: cellData[indexPath.row], atIndexPath: indexPath, selected: selectedIndexpaths)
return cell
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
return 30.0
}
override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let cell = tableView.cellForRow(at: indexPath) as! MyCell
cell.buttonClicked(UIButton())
}
func cellButtonClicked(_ indexPath: IndexPath) {
if selectedIndexpaths.contains(indexPath) {
//this means cell has already selected state
//now we will toggle the state here from selected to unselected by removing indexPath
if let index = selectedIndexpaths.index(of: indexPath) {
selectedIndexpaths.remove(at: index)
}
} else {
//this is new selection so add it
selectedIndexpaths.append(indexPath)
}
tableView.reloadData()
}
}
qazxswpoi
以上是关于UITableView自定义单元格按钮从主视图中选择其他按钮?的主要内容,如果未能解决你的问题,请参考以下文章
iPhone:如何从视图控制器中获取自定义单元格的按钮操作?
UItableview 在自定义单元格上使用带有提示的警报视图重新加载数据的问题