UITableViewCell带动作的按钮

jac*_*k87 13 uibutton uitableview ios swift swift3

嗨,我有一个自定义UITableViewCell,有三个按钮来处理购物车功能,加号,减号和删除按钮,我需要知道哪个单元格被触摸.

我已经尝试使用"标签解决方案"但由于电池的生命周期而无法正常工作.

有谁能帮我找到解决方案?

提前致谢

ped*_*uan 54

我正在UITableViewCell的子类中使用单元委托方法解析它.

快速概述:

1) 创建协议

protocol YourCellDelegate : class {
    func didPressButton(_ tag: Int)
}
Run Code Online (Sandbox Code Playgroud)

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)
    }         
    ...
}
Run Code Online (Sandbox Code Playgroud)

3) 您的视图控制器符合YourCellDelegate上面实现的协议.

class YourViewController: ..., YourCellDelegate {  ... }
Run Code Online (Sandbox Code Playgroud)

4) 在定义单元格(重新使用)后设置委托.

let cell = tableView.dequeueReusableCell(withIdentifier: cellIdentifier, for: indexPath) as! YourCell
cell.cellDelegate = self
cell.btn.tag = indexPath.row
Run Code Online (Sandbox Code Playgroud)

5)在同一个控制器(你实现的UITableView委托/数据源)中,YourCellDelegate协议中放入一个方法.

func didPressButton(_ tag: Int) {
     print("I have pressed a button with a tag: \(tag)")
}
Run Code Online (Sandbox Code Playgroud)

现在,您的解决方案不依赖于标签/数字.您可以根据需要添加任意数量的按钮,这样您就可以通过委托获得响应,无论您要安装多少个按钮.

此协议委托解决方案在iOS逻辑中是首选,它可以用于表格单元格中的其他元素,如UISwitch,UIStepper等等.

  • 对于所有行,cell.tag = indexPath.row只给出0.不应该在步骤2中的sender.tag是self.tag,因为它是您在步骤4中设置为indexPath.row的单元格标记.在步骤2中使用self.tag而不是sender.tag对我来说是预期的. (5认同)
  • 如果 tableview 也实现了部分,您如何解析单元格索引路径的部分? (3认同)

小智 22

快速 4.2

您还可以使用闭包代替委托

1) 在你的 UITableViewCell 中:

 class ExampleCell: UITableViewCell {
    //create your closure here  
         var buttonPressed : (() -> ()) = {}

        @IBAction func buttonAction(_ sender: UIButton) {
    //Call your closure here 
            buttonPressed()
        }
    }
Run Code Online (Sandbox Code Playgroud)

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 
  }
}
Run Code Online (Sandbox Code Playgroud)


小智 15

在社区广泛建议的IBOutlets私有化后,我遇到了同样的问题.

这是我的解决方案:

<在你的细胞类中>

protocol YourCellDelegate: class {
    func didTapButton(_ sender: UIButton)
}

class YourCell: UITableViewCell {

    weak var delegate: YourCellDelegate?

    @IBAction func buttonTapped(_ sender: UIButton) {
        delegate?.didTapButton(sender)
    }
}
Run Code Online (Sandbox Code Playgroud)

<在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
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 你忘了cell.delegate = self in cellforrowatindexpath. (5认同)

Abh*_*tra 8

SWIFT 4. *

它也可以像以下方式完成,不需要太多的编码和委托,简单易行。

将以下代码放入cellForItemAtfor UICollectionView或in cellForRowAtUITableView

cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)
Run Code Online (Sandbox Code Playgroud)

您的方法将是

@objc func buttonSelected(sender: UIButton){
    print(sender.tag)
}
Run Code Online (Sandbox Code Playgroud)

就这样。


Cha*_*ong 8

@pedrouan 很棒,除了使用按钮的tag选项。在许多情况下,当您设置按钮时tableViewCell,这些按钮将修改 tableView 数据源。(例如 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

您的 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
        }
    }
}
Run Code Online (Sandbox Code Playgroud)