pierreafranck
pierreafranck

Reputation: 443

Get indexPath.row in cell

I try to get the indexPath.row in cell when I click on my button:

@IBAction func cellPlayButtonPressed(_ sender: Any) {
    let cell = (sender as AnyObject).superview??.superview as? UITableViewCell
    let indexPath = runnerTableView.indexPath(for: cell!)
    print(indexPath)
}

I have this error when I push my button:

fatal error: unexpectedly found nil while unwrapping an Optional value

I have try everything found on Stack Overflow and nothing is working.

Let me know where is the bug! Thanks :)

Upvotes: 1

Views: 674

Answers (5)

Sandip Patel - SM
Sandip Patel - SM

Reputation: 3394

I have created demo and tested for same its working as aspect. You can use as below:

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

        let fruitName = fruits[indexPath.row]
        cell.textLabel?.text = fruitName
        cell.detailTextLabel?.text = "Delicious!"
        cell.imageView?.image = UIImage(named: fruitName)

        //Button added for click event
        let btn = UIButton.init(frame: CGRect(x: 10, y: 10, width: 100, height: 30))
        btn.backgroundColor = UIColor.red
        btn.setTitle("Click Here", for: UIControlState.normal)
        btn.addTarget(self, action: #selector(clickMe), for: .touchUpInside)
        cell.addSubview(btn)

        return cell
    }

    func clickMe(sender : UIButton){

        let indexpath : NSIndexPath =  self.indexPathForCellContainingView(view: sender, inTableView: self.tableView)
        print("Current IndexPath Row : \(indexpath.row) Column : \(indexpath.section)")

    }

     func indexPathForCellContainingView(view: UIView, inTableView tableView: UITableView) -> NSIndexPath {
        let viewCenterRelativeToTableview = tableView.convert(CGPoint(x: view.bounds.midX, y: view.bounds.midY), from: view)
        let cellIndexPath = tableView.indexPathForRow(at: viewCenterRelativeToTableview)!
        return cellIndexPath as NSIndexPath
    }

Upvotes: -1

Pedro Pinho
Pedro Pinho

Reputation: 662

You can send the indexPath for your cell when your are in cellForRowAtIndexPath. And then you have access to the indexPath.

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

let UITableViewCell =  tableView.dequeueReusableCell(withIdentifier: String(describing: UITableViewCell.self), for: indexPath) as! UITableViewCell
cell.indexPath = indexPath
return cell

}

@IBAction func cellPlayButtonPressed(_ sender: UIButton) {

}

Upvotes: -4

Vlad Khambir
Vlad Khambir

Reputation: 4383

Try this code:

@IBAction func cellPlayButtonPressed(_ sender: Any) {
    guard let button = sender as? UIButton else { return }
    let indexPath = tableView.indexPathForRow(at: button.center)
    print(indexPath)
}

Upvotes: 1

Pramod Kumar
Pramod Kumar

Reputation: 2652

just copy the given extension

extension UITableView {    
func indexPath(forItem: AnyObject) -> IndexPath? {
    let itemPosition: CGPoint = forItem.convert(CGPoint.zero, to: self)
    return self.indexPathForRow(at: itemPosition)
}}

USE:

@IBAction func cellPlayButtonPressed(_ sender: Any) {
    if let indexPath = runnerTableView.indexPath(forItem: sender) {
        print(indexPath)
    }
}

Upvotes: 3

Slayter
Slayter

Reputation: 1170

When you set up your cell in cellForRow set the tag property of your button to the indexPath.row of the cell. Then change your method signature to the following:

@IBAction func cellPlayButtonPressed(_ sender: UIButton) {
    // sender.tag == indexPath.row
}

If your button is a class other than UIButton you can replace that with whatever your class is.

Upvotes: -2

Related Questions