ios 带有动作的 UITableViewCell 按钮

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/39947076/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 10:32:50  来源:igfitidea点击:

UITableViewCell Buttons with action

iosswiftuitableviewuibuttonswift3

提问by Hyman87

Hi I have a custom UITableViewCell with three buttons to handle a shopping cart function, Plus,Minus and Delete button and I need to know which cell has been touched.

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

I've already tried to use the "tag solution" but it isn't working due to the lifecycle of the cells.

我已经尝试使用“标签解决方案”,但由于细胞的生命周期,它不起作用。

Can anyone please help me find a solution?

任何人都可以帮我找到解决方案吗?

Thanks in advance

提前致谢

回答by pedrouan

I was resolving this using a cell delegate method within UITableViewCell's subclass.

我正在使用 UITableViewCell 的子类中的单元委托方法解决这个问题。

Quick overview:

快速概览:

1)Create a protocol

1)创建协议

protocol YourCellDelegate : class {
    func didPressButton(_ tag: Int)
}

2)Subclassyour UITableViewCell(if you haven't done so):

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)Letyour view controllerconform to YourCellDelegateprotocol that was implemented above.

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

class YourViewController: ..., YourCellDelegate {  ... }

4)Set a delegate, after the cell has been defined (for reusing).

4)在定义单元格后设置一个委托(用于重用)。

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

5)In the same controller (where is your implemented UITableView delegate/datasource), put a method from YourCellDelegateprotocol.

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

func didPressButton(_ tag: Int) {
     print("I have pressed a button with a tag: \(tag)")
}

Now, your solution is not tag / number dependent. You can add as many buttons as you want, so you are ready to get response via delegate regardless how many buttons you want to install.

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

This protocol-delegate solution is preferred in iOS logic and it can be used for other elements in table cell, like UISwitch, UIStepper, and so on.

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

回答by Frederico

I came across the same problem after making the IBOutlets private as has been broadly suggested by the community.

在按照社区的广泛建议将 IBOutlets 设为私有后,我遇到了同样的问题。

Here is my solution:

这是我的解决方案:

< In your cell class >

<在你的单元格类中>

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

class YourCell: UITableViewCell {

    weak var delegate: YourCellDelegate?

    @IBAction func buttonTapped(_ sender: UIButton) {
        delegate?.didTapButton(sender)
    }
}

< In your ViewController >

< 在你的 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
    }
}

回答by RimK

swift 4.2

快速 4.2

You can also use closures instead of delegates

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

1) In your UITableViewCell :

1) 在你的 UITableViewCell 中:

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

        @IBAction func buttonAction(_ sender: UIButton) {
    //Call your closure here 
            buttonPressed()
        }
    }

2) In your ViewController

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 
  }
}

回答by Abhishek Mitra

SWIFT 4.*

斯威夫特 4.*

It can be done like following way too, Not required much coding and delegation, Simple and easy.

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

Put following code in cellForItemAtfor UICollectionViewor in cellForRowAtfor UITableView

将以下代码放入cellForItemAtforUICollectionView或 in cellForRowAtforUITableView

cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: #selector(buttonSelected), for: .touchUpInside)

And your Method will be

你的方法将是

@objc func buttonSelected(sender: UIButton){
    print(sender.tag)
}

Thats all.

就这样。

回答by Changnam Hong

@pedrouan is great, except using button's tagoption. In many cases, when you set button on tableViewCell, those buttons will modify tableView dataSource.(e.g. InsertRow, DeleteRow).

@pedrouan 很棒,除了使用按钮的tag选项。在许多情况下,当您设置按钮时tableViewCell,这些按钮将修改 tableView 数据源。(例如 InsertRow、DeleteRow)。

But the tag of the button is not updated even if a new cell is insertedor deleted. Therefore, it is better to pass the cellitself as a parameter rather than passing the button's tagto the parameter.

但是即使新单元格是inserted或,按钮的标签也不会更新deleted。因此,最好将其cell本身作为参数传递,而不是将按钮的传递tag给参数。

Here is my example to achieve this.

这是我实现这一目标的示例。

Your ExampleCell

您的 ExampleCell

protocol ExampleCellDelegate: class {
    func didTapButton(cell: ExampleCell)
}

class ExampleCell: UITableViewCell {

    weak var cellDelegate: ExampleCellDelegate?

    @IBAction func btnTapped(_ sender: UIButton) {
        cellDelegate?.didTapButton(cell: self)
    }
}

Your ViewController

您的 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
        }
    }
}

回答by KKRocks

You can also get selected button index using tableViewCell view's hierarchy.

您还可以使用 tableViewCell 视图的层次结构获取选定的按钮索引。

Using following steps :

使用以下步骤:

  1. add selector to the cellForRowAtIndexpath of tableview :

    btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
    
  1. 将选择器添加到 tableview 的 cellForRowAtIndexpath :

    btn?.addTarget(self, action:#selector(buttonPressed(_:)), for:.touchUpInside)
    

2 . get indexPath using following method :

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)
    }

回答by Himanshu Moradiya

UIButton in Tableview cell. Programically create action method in swift 4.2

Tableview 单元格中的 UIButton。在 swift 4.2 中以编程方式创建操作方法

cell.btnlike.addTarget(self, action: #selector(buttonbtnlikePressed(_:event:)), for: .touchUpInside)


@objc func buttonbtnlikePressed(_ sender: Any, event: Any) {
        let point : CGPoint = (sender as AnyObject).convert(CGPoint.zero, to:tblPost)
        var indexPath =  self.tblPost!.indexPathForRow(at: point)
        if let btnlike = sender as? UIButton{
            if btnlike.isSelected{
                btnlike.isSelected = false
            }else{
                btnlike.isSelected = true
            }
        }
    }