1

I would like to implement feature that if profileImage tapped in tableviewCell, segue to detailView. I add tapGesture but I still can't figure out how to get indexPath to pass data. I tried like this but app will crash.

    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

        if segue.identifier == "detailSegue" {
            let next: DetailViewController = segue.destination as! DetailViewController
          // pattern1
 let indexPath = tableView.indexPath(for: sender as! CustomTableViewCell)
         // pattern2
        let indexPath = tableView.indexPathForSelectedRow! as NSIndexPath

            next.data = datas[indexPath.row]
        }
    }

How can I fix this? Thank you in advance!

Daibaku
  • 11,416
  • 22
  • 71
  • 108
  • 1
    Take a button in which you set the profile image. Then make button action and call segue method respect to indexpath.row. Its better way – Khawar Islam Feb 12 '18 at 05:18
  • 1
    You may get help from: https://stackoverflow.com/questions/28659845/swift-how-to-get-the-indexpath-row-when-a-button-in-a-cell-is-tapped – Rocky Feb 12 '18 at 05:24
  • You can get index path refer this:- https://stackoverflow.com/a/42364716/6818278 – Anuraj Feb 12 '18 at 06:43

5 Answers5

5

If you add UITapGestureRecognizer to an UIImageView then don't forget to set isUserInteractionEnabled property to true.

Create a variable to store selected indexPath.row

var selectedCell:Int!

In cellForRow method add gesture to the image view.

let tapGesture = UITapGestureRecognizer(target: self, action: #selector(self.tapBtnAction(_:)))
cell.imageView.tag = indexPath.row
cell.imageView.addGestureRecognizer(tapGesture)

In target method perform segue

func tapBtnAction(_ sender: UITapGestureRecognizer) {
    print("\(sender.view.tag) Tapped")
    self.selectedCell = sender.view.tag
    self.performSegueWithIdentifier("detailSegue", sender: self)
}

In prepareforsegue method get data from the array.

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {

   if segue.identifier == "detailSegue" {
      let next: DetailViewController = segue.destination as! DetailViewController
       next.data = datas[self.selectedCell]
   }
}
RajeshKumar R
  • 15,445
  • 2
  • 38
  • 70
3

Solution 1 : use touchBegun method, make sure imageView UserInteraction is enable

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    let touch = touches.first
      if let cell = touch?.view?.superview?.superview as? YourCellClass {
        let indexPath = yourTablView.indexPath(for: cell)
    //Do whatever you want
    }
}

Solution 2: you can use button.

@IBAction func onBtnClick(_ sender : UIButton) {
    if let cell = sender.superview?.superview as? UITableViewCell {
        let indexPath = tbl_songsInfo.indexPath(for: cell)
    //Do whatever you want
    }
}

Solution 3 : Same as above but use sender.tag

@IBAction func onBtnClick(_ sender : UIButton) {
    let data = yourDataArray[sender.tag] 
    //Do whatever you want
}
Pratik Prajapati
  • 1,137
  • 1
  • 13
  • 26
  • This is a very fragile solution that should be avoided. This code relies in a combination of undocumented `UITableView` subview structure and an assumption on how the sender was added to the cell. There are much simpler and safer solutions. – rmaddy Jun 30 '18 at 15:25
3

1: set tag of ImageView in cellForRowAtIndexpath method , tag will be equal to indexPath.row

imgView.tag = indexPath.row

2: add a target to tapGuestureRecognizer attached on imageView

3: get tag of imageView in that method

let imgView = sender as! UIImageView
let tag = imgView.tag

4: get data accordingly ,and push

let next = self.storyBoard.instatiateViewController(WithIdentifer:"detailVC") 
next.data = datas[tag]
self.navigationController.pushViewController(next)
krishan kumar
  • 378
  • 6
  • 11
2

I have made a sample project to demonstrate the solution. It is working perfectly fine. See the gif! enter image description here

You can download the sample project code using the link https://drive.google.com/file/d/1zF8Uq2H6eQYyrHU6KqnZu7b5cU_HtZY0/view?usp=sharing

Actually, you have to add a gesture recognizer to your image and attach an action to this gesture. See the implementation of cellforRowAt.

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

 let cell = tableView.dequeueReusableCell(withIdentifier:"TableViewCellUser") as! TableViewCellUser
 //handle image and its gesture

 cell.imgUser.image = userImagesArray[indexPath.row]
 //enable the interaction so that touch could be captured.
 cell.imgUser.isUserInteractionEnabled = true
 let gesture = UITapGestureRecognizer(target: self, action:  #selector(userImageTapped(gesture:)))
 gesture.numberOfTouchesRequired = 1
 gesture.delegate = self as? UIGestureRecognizerDelegate
 cell.imgUser.tag = indexPath.row
 cell.imgUser.addGestureRecognizer(gesture)
 //handle label
 cell.lblUserName.text = userNames[indexPath.row]
 return cell

}

//action on user tap

guard let indexPathRow = gesture.view?.tag else {
  return
}
print(indexPathRow)
guard indexPathRow >= 0 else {
  print("Array index must be greater than zero. Going to  return")
  return
}
selectedUserImage = userImagesArray[indexPathRow]
selectedUserName = userNames[indexPathRow]
self.performSegue(withIdentifier: "UsersToDetail", sender: self)

You can download the fully working code from the above mentiond link. Let me know in comments if any problem Occurs

This link will also help [UITapGestureRecognizer tag]: unrecognized selector sent to instance

Awais Fayyaz
  • 2,275
  • 1
  • 22
  • 45
1

There are multiple ways to achieve this, but the easiest way would be adding the UIButton above the UIImageView. and setting the tag of the UIButton with respect to IndexPath of the UITableViewCell and add the click event of the UIButton.

cell.btnImage.tag = indexPath.row

when the user tries to click the UIImage, UIButton above the image will be clicked and click event of the button will be triggered, here you can you can get the index of the UIButton tapped which is same as UIImageView in that particular cell.

@IBAction func BtnClick(_ sender : UIButton) {

     print(sender.tag)//here you will get the IndexPath for that particular UIImageView in Cell.

}