I have multiple section , each cell has a button how to know indexpath.row and indexpath.section if user clicks a button

Viewed 458

Using this code i only get tag which has indexpath.row how to make a button event from it.

TaskPlayButton is my button on that i am passing indexpath.row for single section this would have worked by now how to do on multiple section.

Is there any other way of knowing which button is clicked?

    func numberOfSections(in tableView: UITableView) -> Int {
        return mobileBrand.count
    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return mobileBrand[section].modelName?.count ?? 0
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell

        cell.TaskName.text = mobileBrand[indexPath.section].modelName?[indexPath.row]

        cell.TaskPlayButton.tag = indexPath.row

        cell.TaskPlayButton.addTarget(self, action: #selector(PlayBtnClicked( _:)), for: UIButton.Event.touchUpInside)
         return cell
    }

    func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
        let view = UIView(frame: CGRect(x: 0, y: 0, width: tableView.frame.width, height: 40))
        view.backgroundColor = UIColor.rgb(red: 245, green: 245, blue: 245)

        let lbl = UILabel(frame: CGRect(x: 15, y: 0, width: view.frame.width - 15, height: 40))
        lbl.font = UIFont.systemFont(ofSize: 20)
        lbl.text = mobileBrand[section].brandName
        view.addSubview(lbl)



        return view
    }

    func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
        return 40
    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        if selectedIndex == indexPath.row && isCollapse == true && selectedSection == indexPath.section{
            return 240

        }else{
            return 60
        }
    }

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)
        if selectedIndex == indexPath.row && selectedSection == indexPath.section{
            if self.isCollapse == false
            {
                self.isCollapse = true
            }else{
                self.isCollapse = false
            }
        }else{
            self.isCollapse = true
        }
        self.selectedIndex = indexPath.row
        self.selectedSection = indexPath.section
        TaskTableView.beginUpdates()
        TaskTableView.endUpdates()
    }

    @objc func PlayBtnClicked(_ sender : UIButton)
    {
        print(sender.tag)
    }
4 Answers

you can use closure, please look to my codes :

class YourTableViewCell: UITableViewCell {

    var button: UIButton!

    var buttonAction: ((UIButton) -> Void)?

    @objc func buttonPressed(_ sender : UIButton)) {
        self.buttonAction?(sender)
    }
}

Implement it to your table view delegate :

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "TaskCell", for: indexPath) as! TaskCell

    cell.TaskName.text = mobileBrand[indexPath.section].modelName?[indexPath.row]
    cell.TaskPlayButton.tag = indexPath.row

    cell.buttonAction = { sender in
        // do your action
        // in here, you can get indexPath.row and indexPath.section
    }

    cell.TaskPlayButton.addTarget(self, action: #selector(PlayBtnClicked( _:)), for: UIButton.Event.touchUpInside)
         return cell
}

Hope this answer can help you :)

you can use another method like pass tag to button like this

cell.button.tag = (indexpath.section * 1000) + indexpath.row

now on your button action you can get like

let row = sender.tag%1000
let section = sender/1000
  1. Pass indexPath to cell, when click the button in this cell, you could get the current indexPath

  2. Custom a button hold a property: indexPath. Pass indexPath to the button in the method cellForRowAt. When you click the button, you could use button.indexPath to get what you want.

I just give you quick tip. It just help you on all table view in your project. You can follow my answer here - https://stackoverflow.com/a/62481414/8135121

Here it's for you. You can grab it by position of your button. I explain it to you.

Make a common table view extension on your class. Just use this.

extension UITableView {
    
    func getCellFrom(sender : UIView,completion : @escaping (UITableViewCell,IndexPath)->()){
        var superview = sender.superview
        while let view = superview, !(view is UITableViewCell) {
            superview = view.superview
        }
        guard let cell = superview as? UITableViewCell else {
            return
        }
        guard let indexPath = self.indexPath(for: cell) else {
            return
        }
        completion(cell,indexPath)
    }
}

Set target from cell in your cell for row at IndexPath function.

cell.TaskPlayButton.addTarget(self, action: #selector(PlayBtnClicked( _:)), for: UIButton.Event.touchUpInside)

Call this in PlayBtnClicked action method.

tableView.getCellFrom(sender: sender) { [weak self] (cell, indexPath) in
      // Just use indexPath in here
      //This closure return your cell and your button's indexPath also
   }

Related