自定义 UITableViewCell 中的 UIButton 导致在多个单元格中选择按钮
Posted
技术标签:
【中文标题】自定义 UITableViewCell 中的 UIButton 导致在多个单元格中选择按钮【英文标题】:UIButton inside custom UITableViewCell causes button to be selected in multiple cells 【发布时间】:2016-02-17 12:18:54 【问题描述】:UITableView 的目标是在其旁边显示带有自定义样式复选框的名称。但不知何故,当我点击复选框时,UITableView 中的多个复选框被选中。
我已经从不同的问题搜索并实施了多种解决方案,但似乎没有一个有效。
自定义 UITableViewCell
import UIKit
class NameTableViewCell: UITableViewCell
var name = UILabel()
let checkboxImage_unchecked = UIImage(named: "cellViewCheckbox_unchecked")
let checkboxImage_checked = UIImage(named: "cellViewCheckbox_checked")
let checkbox:UIButton
weak var delegate:HandleCellInteractionDelegate?
override init(style: UITableViewCellStyle, reuseIdentifier: String!)
self.checkbox = UIButton(frame: CGRectMake(35, 16, self.checkboxImage_unchecked!.size.width/2, self.checkboxImage_unchecked!.size.height/2))
super.init(style: style, reuseIdentifier: reuseIdentifier)
self.backgroundColor = UIColor.transparant()
self.checkbox.setBackgroundImage(self.checkboxImage_unchecked, forState: .Normal)
self.checkbox.setBackgroundImage(self.checkboxImage_checked, forState: .Selected)
self.name = UILabel(frame: CGRectMake(97,18,200, 30))
self.addSubview(self.name)
self.addSubview(self.checkbox)
required init?(coder aDecoder: NSCoder)
fatalError("init(coder:) has not been implemented")
override func setSelected(selected: Bool, animated: Bool)
super.setSelected(selected, animated: animated)
func checkboxPushed(sender:AnyObject)
self.checkbox.selected = !self.checkbox.selected
self.delegate?.didPressButton(self)
在协议中,我声明了一个方法 didPressButton 作为按下按钮时的回调(委托需要实现它)
协议
import UIKit
protocol HandleCellInteractionDelegate:class
func didPressButton(cell:NameTableViewCell)
视图控制器
import UIKit
class NameViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, HandleCellInteractionDelegate
var nameView:NameView
get
return self.view as! NameView
var names:[Name]?
var firstLetters:[String]?
let cellIdentifier = "nameCell"
override func viewDidLoad()
super.viewDidLoad()
// Do any additional setup after loading the view.
//self.view.backgroundColor = UIColor.darkSalmon()
override func loadView()
let bounds = UIScreen.mainScreen().bounds
self.view = NameView(frame: bounds)
if(NSUserDefaults.standardUserDefaults().objectForKey("gender") !== nil)
self.loadJSON()
self.getFirstLetters();
self.nameView.tableView.delegate = self;
self.nameView.tableView.dataSource = self;
self.nameView.tableView.registerClass(NameTableViewCell.classForCoder(), forCellReuseIdentifier: "nameCell")
self.nameView.tableView.separatorStyle = .None
self.nameView.tableView.rowHeight = 66.5
func loadJSON()
let path = NSBundle.mainBundle().URLForResource("names", withExtension: "json")
let jsonData = NSData(contentsOfURL: path!)
self.names = NamesFactory.createFromJSONData(jsonData!, gender: NSUserDefaults.standardUserDefaults().integerForKey("gender"))
func getFirstLetters()
var previous:String = ""
for name in self.names!
let firstLetter = String(name.name.characters.prefix(1))
if firstLetter != previous
previous = firstLetter
self.firstLetters?.append(firstLetter)
print(firstLetter)
override func didReceiveMemoryWarning()
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
return (self.names!.count)
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
return nameCellAtIndexPath(indexPath)
func nameCellAtIndexPath(indexPath:NSIndexPath) -> NameTableViewCell
let cell = self.nameView.tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! NameTableViewCell
self.setNameForCell(cell, indexPath: indexPath)
cell.delegate = self;
cell.checkbox.addTarget(cell, action: "checkboxPushed:", forControlEvents: .TouchUpInside)
return cell
func setNameForCell(cell:NameTableViewCell, indexPath:NSIndexPath)
let item = self.names![indexPath.row] as Name
cell.name.text = item.name
func didPressButton(cell: NameTableViewCell)
print(cell)
我做错了什么以及如何解决?
【问题讨论】:
在单元格中添加目标,而不是在视图控制器中。多重选择是立即的,还是仅在您滚动时? @Wain 我不知道它是否是即时的,因为它从不可见的单元格中选择按钮,但是当我滚动时,按钮的选中状态消失 【参考方案1】:您必须保存复选框状态。向您的模型(名称)添加一个属性,例如 checkboxStatus。我希望您将拥有 indexpath.row。 在 nameCellAtIndexPath 这一行之后
cell.delegate = self;
这样设置标签
cell.tag = indexPath.row;
在委托方法中,
func didPressButton(cell: NameTableViewCell)
print(cell)
let item = self.names![cell.tag] as Name
item.checkboxstatus = cell.checkbox.selected
只有一个重要的变化,
func nameCellAtIndexPath(indexPath:NSIndexPath) -> NameTableViewCell
let cell = self.tableView.dequeueReusableCellWithIdentifier(cellIdentifier) as! NameTableViewCell
self.setNameForCell(cell, indexPath: indexPath)
cell.delegate = self;
cell.tag = indexPath.row;
cell.checkbox.addTarget(cell, action: "checkboxPushed:", forControlEvents: .TouchUpInside)
let item = self.names![cell.tag] as Name
cell.checkbox.selected = item.checkboxstatus
return cell
干杯!
【讨论】:
【参考方案2】:这是因为 UITableViewCell 正在被重用。
您在按下复选框时更改了单元格,您需要在数据源模型中跟踪它。
在cellForRowAtIndexPath
中,您必须添加一个条件来检查该复选框是否被选中。然后相应地显示相应的视图。
编辑:
在您的示例中,您需要检查 nameCellAtIndexPath
是否选中复选框,然后正确显示。
【讨论】:
感谢您的快速回复!我会尽快试试这个:)以上是关于自定义 UITableViewCell 中的 UIButton 导致在多个单元格中选择按钮的主要内容,如果未能解决你的问题,请参考以下文章
在 Storyboard 中设计的自定义 UITableViewCell 中的自定义 UIView
ios开发UI篇—使用纯代码自定义UItableviewcell实现一个简单的微博界面布局
iOS开发UI篇—使用xib自定义UItableviewcell实现一个简单的团购应用界面布局
将自定义 UITableViewCell 从 nib 加载到 Swift 中的 UIViewController