您好我有一个带有三个按钮的自定义UITableViewCell来处理购物车功能,Plus,Minus和Delete按钮,我需要知道哪个单元格已被触摸。
我已经尝试使用“标签解决方案”但由于电池的生命周期而无法正常工作。
有人可以帮我找一个解决方案吗?
提前致谢
答案 0 :(得分:48)
我是在UITableViewCell的子类中使用单元委托方法解析它。
快速概述:
1) 创建协议
protocol YourCellDelegate : class {
func didPressButton(_ tag: Int)
}
2) 子类您的 UITableViewCell
(如果您还没有这样做):
class YourCell : UITableViewCell
{
var cellDelegate: YourCellDelegate?
@IBOutlet weak var btn: UIButton!
// connect the button from your cell with this method
@IBAction func buttonPressed(_ sender: UIButton) {
cellDelegate?.didPressButton(sender.tag)
}
...
}
3) 让您的观点控制器符合上面实施的YourCellDelegate
协议。
class YourViewController: ..., YourCellDelegate { ... }
4) 在定义单元格后设置委托(重复使用)。
let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.cellDelegate = self
cell.btn.tag = indexPath.row
5)在同一个控制器中(您实现的UITableView委托/数据源),从YourCellDelegate
协议中添加方法。
func didPressButton(_ tag: Int) {
print("I have pressed a button with a tag: \(tag)")
}
现在,您的解决方案不依赖于标签/数字。您可以根据需要添加任意数量的按钮,因此无论您要安装多少个按钮,都可以通过委托获得响应。
此协议委托解决方案在iOS逻辑中是首选,它可用于表格单元格中的其他元素,如UISwitch
,UIStepper
等。
答案 1 :(得分:13)
在IBOutlets私有化后,我遇到了同样的问题,社区广泛建议。
这是我的解决方案:
<在您的手机类>
中protocol YourCellDelegate: class {
func didTapButton(_ sender: UIButton)
}
class YourCell: UITableViewCell {
weak var delegate: YourCellDelegate?
@IBAction func buttonTapped(_ sender: UIButton) {
delegate?.didTapButton(sender)
}
}
<在您的ViewController>
中class ViewController: UIViewController, YourCellDelegate {
func didTapButton(_ sender: UIButton) {
if let indexPath = getCurrentCellIndexPath(sender) {
item = items[indexPath.row]
}
}
func getCurrentCellIndexPath(_ sender: UIButton) -> IndexPath? {
let buttonPosition = sender.convert(CGPoint.zero, to: tableView)
if let indexPath: IndexPath = tableView.indexPathForRow(at: buttonPosition) {
return indexPath
}
return nil
}
}
答案 2 :(得分:3)
您还可以使用tableViewCell视图的层次结构获取选定的按钮索引。
使用以下步骤:
将选择器添加到tableview的cellForRowAtIndexpath:
btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
2。使用以下方法获取indexPath:
func buttonPressed(_ sender: AnyObject) {
let button = sender as? UIButton
let cell = button?.superview?.superview as? UITableViewCell
let indexPath = tblview.indexPath(for: cell!)
print(indexPath?.row)
}
答案 3 :(得分:3)
SWIFT 4。*
它也可以按照以下方式完成,不需要太多编码和委托,简单易用。
将以下代码放在cellForItemAt
UICollectionView
或cellForRowAt
UITableView
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)
你的方法将是
@objc func buttonSelected(sender: UIButton){
print(sender.tag)
}
多数人。
答案 4 :(得分:2)
迅速4.2
您也可以使用闭包代替委托
1)在您的UITableViewCell中:
class ExampleCell: UITableViewCell {
//create your closure here
var buttonPressed : (() -> ()) = {}
@IBAction func buttonAction(_ sender: UIButton) {
//Call your closure here
buttonPressed()
}
}
2)在您的ViewController中
class ViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as! ExampleCell
cell.buttonPressed = {
//Code
}
return cell
}
}
答案 5 :(得分:1)
UIButton。在Swift 4.2中以编程方式创建动作方法
{{1}}
答案 6 :(得分:0)
@pedrouan很棒,除了使用按钮的tag
选项。在许多情况下,当您在tableViewCell
上设置按钮时,这些按钮将修改tableView dataSource。(例如InsertRow,DeleteRow)。
但即使新单元格为inserted
或deleted
,按钮标记也不会更新。因此,最好将cell
本身作为参数传递,而不是将按钮的tag
传递给参数。
这是我实现这个目标的例子。
您的ExampleCell
protocol ExampleCellDelegate: class {
func didTapButton(cell: ExampleCell)
}
class ExampleCell: UITableViewCell {
weak var cellDelegate: ExampleCellDelegate?
@IBAction func btnTapped(_ sender: UIButton) {
cellDelegate?.didTapButton(cell: self)
}
}
您的ViewController
class ViewController: ExampleCellDelegate {
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if let cell = tableView.dequeueReusableCell(withIdentifier: "ExampleCell", for: indexPath) as? ExampleCell {
cell.cellDelegate = self
return cell
}
return UITableViewCell()
}
func didTapButton(cell: ExampleCell) {
if let indexPath = tableView.indexPath(for: cell) {
// do Something
}
}
}