Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to add gesture to UITableViewCell?

I want to add a tap gesture to every cell in a UITableView that edits the content in it. The two ways to add a gesture are in code or through storyboard. I tried both and they failed.

Can I add a gesture to every cell in table with storyboard drag and drop? It seems to only add gesture to the first cell. Adding gesture in code, I wrote something like,

addGestureRecognizer(UITapGestureRecognizer(target: self,action:#selector(MyTableViewCell.tapEdit(_:))))

or

addGestureRecognizer(UITapGestureRecognizer(target: self, action:"tapEdit:"))

both work. But I'd like to let the UITableViewController handle this gesture because it does something with the datasource. How do I write my target and action?

EDIT:

addGestureRecognizer(UITapGestureRecognizer(target: MasterTableViewController.self, action:#selector(MasterTableViewController.newTapEdit(_:)))

it induce an error said, unrecognized selector sent to class 0x106e674e0...

like image 759
Fate Riddle Avatar asked Jun 08 '16 03:06

Fate Riddle


People also ask

What is UITapGestureRecognizer Swift?

UITapGestureRecognizer is a concrete subclass of UIGestureRecognizer . For gesture recognition, the specified number of fingers must tap the view a specified number of times. Although taps are discrete gestures, they're discrete for each state of the gesture recognizer.


2 Answers

To add gesture to UITableViewCell, you can follow the steps below:

First, add gesture recognizer to UITableView

tapGesture = UITapGestureRecognizer(target: self, action: #selector(tableViewController.tapEdit(_:)))
tableView.addGestureRecognizer(tapGesture!)
tapGesture!.delegate = self

Then, define the selector. Use recognizer.locationInView to locate the cell you tap in tableView. And you can access the data in your dataSource by tapIndexPath, which is the indexPath of the cell the user tapped.

func tapEdit(recognizer: UITapGestureRecognizer)  {
    if recognizer.state == UIGestureRecognizerState.Ended {
        let tapLocation = recognizer.locationInView(self.tableView)
        if let tapIndexPath = self.tableView.indexPathForRowAtPoint(tapLocation) {
            if let tappedCell = self.tableView.cellForRowAtIndexPath(tapIndexPath) as? MyTableViewCell {
                //do what you want to cell here

            }
        }
    }
}

It is possible to add gesture directly to TableView cell and access the datasource in viewController, You need to set up a delegate:

In your custom cell:

import UIKit


class MyTableViewCell: UITableViewCell {

    var delegate: myTableDelegate?

    override func awakeFromNib() {
        super.awakeFromNib()

        let tapGesture = UITapGestureRecognizer(target: self, action: #selector(MyTableViewCell.tapEdit(_:)))
        addGestureRecognizer(tapGesture)
        //tapGesture.delegate = ViewController()

    }

    func tapEdit(sender: UITapGestureRecognizer) {
        delegate?.myTableDelegate()
    }

}

protocol myTableDelegate {
    func myTableDelegate() 
}

In your viewController:

import UIKit

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource, UIGestureRecognizerDelegate, myTableDelegate {

    @IBOutlet var tableView: UITableView!

    override func viewDidLoad() {
        super.viewDidLoad()

        tableView.delegate = self
        tableView.dataSource = self
        // Do any additional setup after loading the view, typically from a nib.
    }

    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 35
    }

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as? MyTableViewCell

        cell?.delegate = self

        return cell!
    }

    func myTableDelegate() {
        print("tapped")
        //modify your datasource here
    }

}

However, this method could cause problems, see UIGestureRecognizer and UITableViewCell issue. In this case, when the swipe gesture successes, the selector get called twice for some reason. I can't say the second method is a bad one as I haven't found any direct evidence yet, but after searching through Google, it seems like the first method is the standard way.

like image 133
ilovecomputer Avatar answered Oct 11 '22 10:10

ilovecomputer


You don't need to add gesture recognizer to achieve what you are doing.

  • Use the UITableViewDelegate method tableView:didSelectRowAtIndexPath: to detect which row is tapped (this is what exactly your tapGesture is going to do) and then do your desired processing.
  • If you don't like the gray indication when you select cell, type this in your tableView:didEndDisplayingCell:forRowAtIndexPath: just before returning the cell:
    cell?.selectionStyle = .None
like image 40
Rohan Sanap Avatar answered Oct 11 '22 08:10

Rohan Sanap