Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Getting UITableViewCell from UITapGestureRecognizer

I have a UITableView with multiple sections and in my cellForRowAtIndexPath method I add a UITapGestureRecognizer to the cell's imageView (each cell has a small image). I have been successful in accessing that image (in order to change it) by using:

var imageView : UIImageView! = sender.view! as UIImageView

What I need to do now, however, is access the cell's data, which I believe means I need to be able to access the cell in order to get the section and row number. Can anyone advise on how to do this? The idea is that I am changing the image to an unchecked checkbox if the task is done, but then in my data I need to actually mark that task as done.

like image 265
iOSBeginner Avatar asked Mar 31 '15 04:03

iOSBeginner


3 Answers

In your function that handles the tap gesture recognizer, use tableView's indexPathForRowAtPoint function to obtain and optional index path of your touch event like so:

func handleTap(sender: UITapGestureRecognizer) {
    let touch = sender.locationInView(tableView)
    if let indexPath = tableView.indexPathForRowAtPoint(touch) {
        // Access the image or the cell at this index path
    }
}

From here, you can call cellForRowAtIndexPath to get the cell or any of its content, as you now have the index path of the tapped cell.

like image 197
Ian Avatar answered Sep 18 '22 09:09

Ian


You can get the position of the image tapped in order to find the indexPath and from there find the cell that has that image:

var position: CGPoint =  sender.locationInView(self.tableView)
var indexPath: NSIndexPath = self.tableView.indexPathForRowAtPoint(position)!    
var cell = self.tableView(tableView, cellForRowAtIndexPath: indexPath)
like image 38
EI Captain v2.0 Avatar answered Sep 17 '22 09:09

EI Captain v2.0


You're missing that you can use the Delegate design pattern here.

Create a protocol that tells delegates the state changes in your checkbox (imageView):

enum CheckboxState: Int {
    case .Checked = 1
    case .Unchecked = 0
}

protocol MyTableViewCellDelegate {
    func tableViewCell(tableViewCell: MyTableViewCell, didChangeCheckboxToState state: CheckboxState)
}

And assuming you have a UITableViewCell subclass:

class MyTableViewCell: UITableViewCell {

    var delegate: MyTableViewCellDelegate?

    func viewDidLoad() {

        // Other setup here...

        let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: "didTapImage:")
        imageView.addGestureRecognizer(tapGestureRecognizer)
        imageView.userInteractionEnabled = true
    }

    func didTapImage(sender: AnyObject) {

        // Set checked/unchecked state here
        var newState: CheckboxState = .Checked // depends on whether the image shows checked or unchecked

        // You pass in self as the tableViewCell so we can access it in the delegate method
        delegate?.tableViewCell(self, didChangeCheckboxToState: newState)
    }

}

And in your UITableViewController subclass:

class MyTableViewController: UITableViewController, MyTableViewCellDelegate {

    // Other methods here (viewDidLoad, viewDidAppear, etc)...

    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) {
        var cell = tableView.dequeueReusableCellWithIdentifier("YourIdentifier", forIndexPath: indexPath) as MyTableViewCell

        // Other cell setup here...

        // Assign this view controller as our MyTableViewCellDelegate
        cell.delegate = self

        return cell
    }

    override func tableViewCell(tableViewCell: MyTableViewCell, didChangeCheckboxToState state: CheckboxState) {

        // You can now access your table view cell here as tableViewCell

    }

}

Hope this helps!

like image 23
Jaune Sarmiento Avatar answered Sep 17 '22 09:09

Jaune Sarmiento