obtener indexPath de UITableViewCell al hacer clic en Button from Cell

Por favor mira esta imagen

Tengo un botón (cruz de color rojo) en UITableViewCell y al hacer clic en ese botón quiero obtener indexPath de UITableViewCell .

En este momento estoy asignando una etiqueta a cada uno de los botones como este cell.closeButton.tag = indexPath.section y al hacer clic en el botón Obtengo el valor de indexPath.section como este:

 @IBAction func closeImageButtonPressed(sender: AnyObject) { data.removeAtIndex(sender.tag) tableView.reloadData() } 

¿Es esta la forma correcta de implementación o hay alguna otra forma limpia de hacerlo?

Use delegates:

MyCell.swift:

 import UIKit //1. delegate method protocol MyCellDelegate: AnyObject { func btnCloseTapped(cell: MyCell) } class MyCell: UICollectionViewCell { @IBOutlet var btnClose: UIButton! //2. create delegate variable weak var delegate: MyCellDelegate? //3. assign this action to close button @IBAction func btnCloseTapped(sender: AnyObject) { //4. call delegate method //check delegate is not nil with `?` delegate?.btnCloseTapped(cell: self) } } 

MyViewController.swift:

 //5. Conform to delegate method class MyViewController: UIViewController, MyCellDelegate, UITableViewDataSource,UITableViewDelegate { //6. Implement Delegate Method func btnCloseTapped(cell: MyCell) { //Get the indexpath of cell where button was tapped let indexPath = self.collectionView.indexPathForCell(cell) print(indexPath!.row) } func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCellWithIdentifier("MyCell") as! MyCell //7. delegate view controller instance to the cell cell.delegate = self return cell } } 

También puede obtener NSIndexPath desde CGPoint esta manera:

 @IBAction func closeImageButtonPressed(sender: AnyObject) { var buttonPosition = sender.convertPoint(CGPointZero, to: self.tableView) var indexPath = self.tableView.indexPathForRow(atPoint: buttonPosition)! } 

Cree una clase personalizada de UIButton y declare una propiedad almacenada como esta y úselo para recuperar indexPath asignado de callFroRowAtIndexPath.

 class VUIButton: UIButton { var indexPath: NSIndexPath = NSIndexPath() } 

Esta es la solución de prueba completa de que su indexPath nunca se equivocará en ninguna condición. Trata una vez.

 // // ViewController.swift // Table // // Created by Ngugi Nduung'u on 24/08/2017. // Copyright © 2017 Ngugi Ndung'u. All rights reserved. // import UIKit class ViewController: UITableViewController{ let identifier = "cellId" var items = ["item1", "2", "3"] override func viewDidLoad() { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. self.title = "Table" tableView.register(MyClass.self, forCellReuseIdentifier: "cellId") } //Return number of cells you need override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int{ return items.count } override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "cellId", for: indexPath) as! MyClass cell.controller = self cell.label.text = items[indexPath.row] return cell } // Delete a cell when delete button on cell is clicked func delete(cell: UITableViewCell){ print("delete") if let deletePath = tableView.indexPath(for: cell){ items.remove(at: deletePath.row) tableView.deleteRows(at: [deletePath], with: .automatic) } } } class MyClass : UITableViewCell{ var controller : ViewController? override init(style: UITableViewCellStyle, reuseIdentifier: String?) { super.init(style: style, reuseIdentifier: reuseIdentifier) setUpViews() } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) fatalError("init(coder:) has not been implemented") } let label : UILabel = { let label = UILabel() label.text = "My very first cell" label.translatesAutoresizingMaskIntoConstraints = false return label }() let btn : UIButton = { let bt = UIButton(type: .system) bt.translatesAutoresizingMaskIntoConstraints = false bt.setTitle("Delete", for: .normal) bt.setTitleColor(.red, for: .normal) return bt }() func handleDelete(){ controller?.delete(cell: self) } func setUpViews(){ addSubview(label) addSubview(btn) btn.addTarget(self, action: #selector(MyClass.handleDelete), for: .touchUpInside) btn.rightAnchor.constraint(equalTo: self.rightAnchor).isActive = true label.leftAnchor.constraint(equalTo: self.leftAnchor, constant: 16).isActive = true label.widthAnchor.constraint(equalTo: self.widthAnchor , multiplier: 0.8).isActive = true label.rightAnchor.constraint(equalTo: btn.leftAnchor).isActive = true } } 

Aquí hay un ejemplo completo que responderá a su pregunta.

En tu cellForRow:

 #import  func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { setAssociatedObject(object: YOURBUTTON, key: KEYSTRING, value: indexPath) } @IBAction func closeImageButtonPressed(sender: AnyObject) { let val = getAssociatedObject(object: sender, key: KEYSTROKING) } 

Aquí val es su objeto indexPath, puede pasar cualquier objeto como puede asignar el objeto de celda de paso y obtenerlo en la acción del botón.

prueba esto:

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell = (tableView.dequeueReusableCell(withIdentifier: "MainViewCell", forIndexPath: indexPath) as! MainTableViewCell) cell.myButton().addTarget(self, action: Selector("myClickEvent:event:"), forControlEvents: .touchUpInside) return cell } 

esta función consigue la posición de clic de fila

 @IBAction func myClickEvent(_ sender: Any, event: Any) { var touches = event.allTouches()! var touch = touches.first! var currentTouchPosition = touch.location(inView: feedsList) var indexPath = feedsList.indexPathForRow(atPoint: currentTouchPosition)! print("position:\(indexPath.row)") } 

En Swift 4, solo usa esto:

botón funcTapped (_ remitente: UIButton) {

 let buttonPostion = sender.convert(sender.bounds.origin, to: tableView) if let indexPath = tableView.indexPathForRow(at: buttonPostion) { let rowIndex = indexPath.row } 

}

Cómo obtener cell indexPath para tocar el botón en Swift 4 con el selector de botones

 @objc func buttonClicked(_sender:UIButton){ let buttonPosition = sender.convert(CGPoint.zero, to: self.tableView) let indexPath = self.tableView.indexPathForRow(at:buttonPosition) let cell = self.tableView.cellForRow(at: indexPath) as! UITableViewCell print(cell.itemLabel.text)//print or get item }