Search code examples
iosswiftuitableviewuigesturerecognizernsindexpath

IndexPath in tablew view cell returned is wrong on click of a label in a UITableView


I have a label inside a table view cell.

On click of the label I want to segue to another view controller after retrieving the correct indexPath.

I have added a gestureRecognizer to the label. On click of the label it returns the wrong indexPath , it does not return the index Path of the cell in which the label is.

How can I solve this problem . Any help will be appreciated. Thank you

Following is my code

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell
    {
        cell = tableView.dequeueReusableCell(withIdentifier: "ViewControllerCell", for: indexPath) as! TableCell

        cell.name.text = feeds[indexPath.row].name

        nameClicked()
        return cell
    }


 func nameClicked(){
        cell.name.isUserInteractionEnabled = true
        let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(TrendViewController.handleTap(gestureRecognizer:)))
        cell.name.addGestureRecognizer(gestureRecognizer)

    }


    func handleTap(gestureRecognizer: UIGestureRecognizer) {

        var touchPoint = cell.name.convert(CGPoint.zero, to: self.tableView)
        var clickedLabelIndexPath = tableView.indexPathForRow(at: touchPoint)!

        nameFromView = feeds[clickedLabelIndexPath.row].name
        print("IndexPath at touch",clickedLabelIndexPath)

        let storyboard = UIStoryboard(name: "Main", bundle: nil)
        let vc = storyboard.instantiateViewController(withIdentifier: "profile") as! ProfileViewController

        vc.clickedLabelIndexPath = clickedLabelIndexPath
        vc.nameFromView = feeds[clickedLabelIndexPath.row].name

        self.navigationController?.pushViewController(vc, animated: true)
    }

Solution

  • You have declare cell as instance property in your class,so you are adding gesture to the same cell's label. So create new cell using dequeueReusableCell and changed your method nameClicked by adding argument of type cell.

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        //create new cell
        let cell = tableView.dequeueReusableCell(withIdentifier: "ViewControllerCell", for: indexPath) as! TableCell
        cell.name.text = feeds[indexPath.row].name
        nameClicked(cell)
        return cell
    }
    
    func nameClicked(_ cell: TableCell){
        cell.name.isUserInteractionEnabled = true
        let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(TrendViewController.handleTap(gestureRecognizer:)))
        cell.name.addGestureRecognizer(gestureRecognizer)
    }
    

    Now change your handleTap method like this to get the correct indexPath.

    func handleTap(_ gestureRecognizer: UIGestureRecognizer) {
        let point = self.tableView.convert(CGPoint.zero, from: gestureRecognizer.view!)
        if let indexPath = self. tableView.indexPathForRow(at: point) {
            print("\(indexPath.section) \(indexPath.row)")
            //Add your code here
        }
    }
    

    Note: If your cell having only single cell then it is batter if you use didSelectRowAt method instead of adding gesture to label.

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        print(indexPath.row)
    }