How can I get indexPath.row in cell.swift

I have 2 files.

  • myTableViewController.swift
  • myTableCell.swift

Is it possible to get indexPath.row in myTabelCell.swift function?

Here is myTableCell.swift

import UIKit import Parse import ActiveLabel class myTableCell : UITableViewCell { //Button @IBOutlet weak var commentBtn: UIButton! @IBOutlet weak var likeBtn: UIButton! @IBOutlet weak var moreBtn: UIButton! override func awakeFromNib() { super.awakeFromNib() } @IBAction func likeBtnTapped(_ sender: AnyObject) { //declare title of button let title = sender.title(for: UIControlState()) //I want get indexPath.row in here! } 

Here is myTableViewController.swift

 class myTableViewController: UITableViewController { //Default func override func viewDidLoad() { super.viewDidLoad() //automatic row height tableView.estimatedRowHeight = 450 tableView.rowHeight = UITableViewAutomaticDimension } // cell config override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //define cell let cell = tableView.dequeueReusableCell(withIdentifier: "myTableCell", for: indexPath) as! myTableCell } 

As you can see ... I'm trying to get indexPath.row in myTableCell, liktBtnTapped.

Could you tell me how can I access or get IndexPath.row?

+23
uitableview swift nsindexpath
source share
9 answers

I created a UIResponder extension with a recursive method that can be used in any UIView (which inherits from UIResponder ) to find the parent representation of a specific type.

 import UIKit extension UIResponder { /** * Returns the next responder in the responder chain cast to the given type, or * if nil, recurses the chain until the next responder is nil or castable. */ func next<U: UIResponder>(of type: U.Type = U.self) -> U? { return self.next.flatMap({ $0 as? U ?? $0.next() }) } } 

Using this, we can extend the UITableViewCell some convenient read-only computed properties to represent the table and cell index paths.

 extension UITableViewCell { var tableView: UITableView? { return self.next(of: UITableView.self) } var indexPath: IndexPath? { return self.tableView?.indexPath(for: self) } } 

Here is how you can use it in your example:

 @IBAction func likeBtnTapped(_ sender: AnyObject) { //declare title of button let title = sender.title(for: UIControlState()) //I want get indexPath.row in here! self.indexPath.flatMap { print($0) } } 
+32
source share

Swift 4+

Try it in your camera.

 func getIndexPath() -> IndexPath? { guard let superView = self.superview as? UITableView else { print("superview is not a UITableView - getIndexPath") return nil } indexPath = superView.indexPath(for: self) return indexPath } 
+11
source share

Easy .. You can do this inside a button action:

 let section = 0 let row = sender.tag let indexPath = IndexPath(row: row, section: section) let cell: myTableCell = self.feedTableView.cellForRow(at: indexPath) as! myTableCell 

And then in cellForRowAtIndexPath :

 // add the row as the tag cell.button.tag = indexPath.row 
+3
source share

Create an indexPath property in the cell class and set it to cellForRowAtIndexPath when the cell is reused.

But there is a caveat: some table view methods for reordering cells do not call cellForRowAtIndexPath . You should consider this case.

But if you always use reloadData() , it is safe and quite easy.


Another way is to translate the control code for the controls into the controller class and run it through callback locks that fix the index path.

+1
source share

Here is another way to do it

 import UIKit import Parse import ActiveLabel class myTableCell : UITableViewCell { //Button @IBOutlet weak var commentBtn: UIButton! @IBOutlet weak var likeBtn: UIButton! @IBOutlet weak var moreBtn: UIButton! override func awakeFromNib() { super.awakeFromNib() } } class myTableViewController: UITableViewController { //Default func //assuming you have an array for your table data source var arrayOfTitles = [String]() override func viewDidLoad() { super.viewDidLoad() //automatic row height tableView.estimatedRowHeight = 450 tableView.rowHeight = UITableViewAutomaticDimension } // cell config override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { //define cell let cell = tableView.dequeueReusableCell(withIdentifier: "myTableCell", for: indexPath) as! myTableCell cell.commentBtn.tag = indexPath.row cell.commentBtn.addTarget(self, action: #selector(likeBtnTapped(_:), forControlEvents:.TouchUpInside) //cell config end @IBAction func likeBtnTapped(sender: UIButton) { let btn = sender let indexP = NSIndexPath(forItem: btn.tag, inSection: 0) let cell = tableView.dequeueReusableCell(withIdentifier: "myTableCell", for: indexP) as! myTableCell //I want get indexPath.row in here! let title = arrayOfTitles[indexP.row] //declare title of button cell.commentBtn.setTitle(title, forState: UIControlState.Normal) } } 
+1
source share

My solution was subclassed by UITableViewCell, so you can add the IndexPath property. Assign a custom class to a table cell in a storyboard. assign IndexPath when calling rowAtIndexPath.

 class MyTableViewCell: UITableViewCell { var indexPath: IndexPath? } 

custom class

 override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { var cell = tableView.dequeueReusableCell(withIdentifier: "cellid1", for: indexPath) (cell as? MyTableViewCell)?.indexPath = indexPath return cell } 
+1
source share

Swift 4.1. Here I created a function to get IndexPath. Just pass in a UIView object (UIButton, UITextField, etc.) And a UITableView object to get IndexPath.

 func getIndexPathFor(view: UIView, tableView: UITableView) -> IndexPath? { let point = tableView.convert(view.bounds.origin, from: view) let indexPath = tableView.indexPathForRow(at: point) return indexPath } 
+1
source share

Another approach to Swift 4.2 and the lack of assumption that Superview will always be a table view

 extension UITableViewCell{ var tableView:UITableView?{ return superview as? UITableView } var indexPath:IndexPath?{ return tableView?.indexPath(for: self) } } 

Usage example

 @IBAction func checkBoxAction(_ sender: UIButton) { guard let indexPath = indexPath else { return } sender.isSelected = !sender.isSelected myCustomCellDelegate?.checkBoxTableViewCell(didSelectCheckBox: sender.isSelected, for: indexPath) } 
+1
source share

Swift 5:

  if let collectionView = superview as? UICollectionView, let index = collectionView.indexPath(for: self) { // stuff } 
0
source share

All Articles