7

I have an action button in UITableViewCell and I would like to detect when the button is pressed and the pressed cell's number from ViewController to make an audio play list in ViewController.swift.

I have been stuck in this problem for a while and I would really appriciate your advice. Here are the codes.

ViewController.swift

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {

    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self

        tableView.register(UINib(nibName: "Cell", bundle: nil), forCellReuseIdentifier: "cell")

    }

    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 3
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! Cell
        return cell

    }


}

Cell.swift

import UIKit

class Cell: UITableViewCell {

    @IBOutlet weak var button: UIButton!

    @IBAction func buttonPressed(_ sender: Any) {

        ***[Code to send the pressed cell's number to ViewController]***

    }

}
rmaddy
  • 314,917
  • 42
  • 532
  • 579
UK4
  • 460
  • 7
  • 25

2 Answers2

12

You could go for a good old fashioned delegate pattern. This has the advantage of not coupling your view controller from your cell. Don't forget to make your delegate weak to avoid retain cycles.

The you can find the cell index path from the table view. (I'm assuming by cell number you mean index path)

protocol CellDelegate: class {
    func didTap(_ cell: Cell)
}

class Cell: UITableViewCell {

    weak var delegate: CellDelegate?
    @IBAction func buttonPressed(_ sender: Any) {
        delegate?.didTap(self)
    }
}

class ViewController: UIViewController, CellDelegate {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = ...
        cell.delegate = self
        return cell
    }

    func didTap(_ cell: Cell) {
        let indexPath = self.tableView.indexPath(for: cell)
        // do something with the index path
    }
}
Binary Pulsar
  • 1,209
  • 10
  • 17
  • 3
    Your implementation of `didTap` is strange. Just do: `let indexPath = self.tableView.indexPath(for: cell)`. No need to scan the visible cells. – rmaddy Nov 24 '17 at 18:27
0

Try this Inside your ViewConroller

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCell(withIdentifier: "cell") as! Cell

        //add tag to cell button to that of cell index
        cell.button.tag = indexPath.row

         //Observer for button click event inside cell
         cell.button.addTarget(self, action: #selector(pressButton(_:)), for: .touchUpInside)

        return cell

    }

//Mark: Button Action

@objc func pressButton(_ button: UIButton) {
    print("Button with tag: \(button.tag) clicked in cell!")
}
Rishu Gupta
  • 43
  • 1
  • 14