Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Adding a gesture recognizer to an image view in a table cell

How can I add a Gesture Recognizer to a UIImageView in a table cell? I want it so that if a user taps an image in the cell, the image will change and the data model will update.

I know this needs to be set up in the UITableViewController. My code currently can execute a command if anywhere in the cell is tapped, but I would like it to execute only if the image is tapped, not anywhere in the cell.

I setup up the gesture recognizer in viewDidLoad

override func viewDidLoad() {
    super.viewDidLoad()

    // Load sample data
    loadSampleHabits()

    // Initialize tap gesture recognizer
    var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
    // Add gesture recognizer to the view
    self.tableView.addGestureRecognizer(recognizer)

And this is the function

//action method for gesture recognizer
func tapEdit(recognizer: UITapGestureRecognizer) {
    if recognizer.state == UIGestureRecognizerState.ended {
        let tapLocation = recognizer.location(in: self.tableView)
        if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
            if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell {
                print("Row Selected")

            }
        }
    }

What the cell looks like

As a secondary question, are there any conflicts if I want to add a gesture recognizer to the cell and the image view within the cell?

like image 976
b.gibson Avatar asked Jul 12 '17 05:07

b.gibson


2 Answers

You are adding gesture recognizer on your tableview instead of imageView as you required. Yo need to move your code from viewDidLoad to cellForRowAtIndexPath and add gesture to imageView in each cell while configuing your cell.

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell{
     var recognizer = UITapGestureRecognizer(target: self, action: #selector(tapEdit(recognizer:)))
     // Add gesture recognizer to your image view
     cell.yourimageview.addGestureRecognizer(recognizer)
}

Note: Do make sure to enable userinteraction of your image view

cell.yourimageview.userInteractionEnabled = YES;

For your requirement I will suggest using UILongPressGestureRecognizer as it has less chances of conflict in gesture and didselect. Yo can add UILongPressGestureRecognizer in viewDidLoad and access it as per your requirement.

let lpgr = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.handleLongPress(_:)))
lpgr.minimumPressDuration = 1
tableView.addGestureRecognizer(lpgr)

Define method as

func handleLongPress(_ gesture: UILongPressGestureRecognizer){
if gesture.state != .began { return }
let tapLocation = gesture.location(in: self.tableView)
    if let tapIndexPath = self.tableView.indexPathForRow(at: tapLocation) {
        if let tappedCell = self.tableView.cellForRow(at: tapIndexPath) as? HabitTableViewCell {
            print("Row Selected")

        }
}

You can try removing if recognizer.state == UIGestureRecognizerState.ended condition from your method.

UITapGestureRecognizer is a discrete gesture, and as such, your event handler is called only once when the gesture was recognized. You don't have to check the state at all. Certainly you won't receive a call for the state of .Began. For more info consider @Rob ans here.

like image 134
luckyShubhra Avatar answered Sep 30 '22 01:09

luckyShubhra


For my suggestion you have to use UIButton in cell, for performance improvements,

UIButtons

Specially designed for this and have been extensively optimized by Apple for touches.

If you want image in cell you can use UIButton with Image inside.

like image 39
Bhavesh Dhaduk Avatar answered Sep 30 '22 02:09

Bhavesh Dhaduk