Search code examples
iosswiftuitableviewuitapgesturerecognizer

Detecting a tap on UILabel inside a cell


I have a UITapGestureRecognizer on a label as:

cell.label.userInteractionEnabled = true
let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(ViewController.labelTapped))
cell.label.addGestureRecognizer(gestureRecognizer)

I’d want it to change text when a user taps on it. After hours of looking for an answer on Stackoverflow, I’ve reached at a point where I could change text of a label. But it also changes text on other cell labels. Here’s what I implemented:

 func labelTapped(recognizer: UIGestureRecognizer){
        print("Label tapped.")

        let position: CGPoint =  recognizer.locationInView(self.tableView)
        let indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(position)!
        let cell = self.tableView.cellForRowAtIndexPath(indexPath) as! DataTableViewCell
        
        cell.label.text = "Test."
    }

Help me find a solution.


Solution

  • I would recommend changing the DataSource as Sneak already mentioned. You can then reload your tableView at specified IndexPaths to get desired result:

    func handleLabelTap(sender: UIGestureRecognizer) {
        // Get references
        guard let label = sender.view as? UILabel else {
            print("Error not a label")
            return
        }
        let position = sender.location(in: self.tableView)
        guard let index = self.tableView.indexPathForRow(at: position) else { 
            print("Error label not in tableView")
            return
         }
    
        // Notify TableView of pending updates
        self.tableView.beginUpdates()
        defer { self.tableView.endUpdates() }
    
        // Alter Datasource
        self.data[index.row] = "Changed Value"
        self.tableView.reloadRows(at: [index], with: .automatic)
    }
    

    Where self.data is an array of String which represents your DataSource.

    Edit: Swift 2.3 version as suggested in comments.

    func handleLabelTap(sender: UIGestureRecognizer) {
        // Get references
        guard let label = sender.view as? UILabel else {
            print("Error not a label")
            return
        } 
        let position = sender.locationInView(self.tableView) 
        guard let index = self.tableView.indexPathForRowAtPoint(position) else { 
            print("Error label not in tableView")
            return
        } 
    
        // Notify TableView of pending updates
        self.tableView.beginUpdates() 
        defer { self.tableView.endUpdates() } 
    
        // Alter DataSource
        self.data[index.row] = "Changed Value" 
        self.tableView.reloadRowsAtIndexPaths([index], withRowAnimation: .Automatic)
    }