ios uitableview uibutton swift2

ios - obtener indexPath de UITableViewCell al hacer clic en el botón de la celda



uibutton swift2 (9)

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 botón como este cell.closeButton.tag = indexPath.section y al hacer clic en el botón obtengo el valor indexPath.section esta manera:

@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?


Cómo obtener el índice de celda Ruta 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 }


Cree una clase personalizada de UIButton y declare una propiedad almacenada como esta y úsela 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.


En Swift 4, solo usa esto:

func buttonTapped (_ remitente: UIButton) {

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

}


En tu cellForRow:

#import <objc/runtime.h> 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 un objeto de celda de paso y ponerlo en acción de botón.


Pruebe con el mejor uso de cierres rápidos: simple, rápido y fácil.

En el método cellForRowAtIndexPath:

let cell = tableView.dequeueReusableCell(withIdentifier: "CustomCellIdentifier", for: indexPath) as! CustomCell cell.btnTick.mk_addTapHandler { (btn) in print("You can use here also directly : /(indexPath.row)") self.btnTapped(btn: btn, indexPath: indexPath) }

Método selector para uso externo del método cellForRowAtIndexPath:

func btnTapped(btn:UIButton, indexPath:IndexPath) { print("IndexPath : /(indexPath.row)") }

Extensión para UIButton:

extension UIButton { private class Action { var action: (UIButton) -> Void init(action: @escaping (UIButton) -> Void) { self.action = action } } private struct AssociatedKeys { static var ActionTapped = "actionTapped" } private var tapAction: Action? { set { objc_setAssociatedObject(self, &AssociatedKeys.ActionTapped, newValue, .OBJC_ASSOCIATION_RETAIN) } get { return objc_getAssociatedObject(self, &AssociatedKeys.ActionTapped) as? Action } } @objc dynamic private func handleAction(_ recognizer: UIButton) { tapAction?.action(recognizer) } func mk_addTapHandler(action: @escaping (UIButton) -> Void) { self.addTarget(self, action: #selector(handleAction(_:)), for: .touchUpInside) tapAction = Action(action: action) } }


También puede obtener NSIndexPath de CGPoint esta manera:

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


Usar delegados:

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


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 obtiene la posición del 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)") }


// // 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.