Weles
Weles

Reputation: 1275

How to pass an object associated with UITapGestureRecognizer

I have a CustomTableViewCell where there is an image. This image is associated with UITapGestureRecognizer.

When i click in this image i need pass the object, based on the cell and indexPath, to the selector, like this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
  let cell = tableView.dequeueReusableCellWithIdentifier("cellTotal") as TotalTableViewCell

  let schedulle = schedulleList[indexPath.row] as Schedulle

  let tap = UITapGestureRecognizer(target: self, action: "edit:")
  tap.numberOfTapsRequired = 1
  tap.numberOfTouchesRequired = 1

  //simulation code - here i need pass the object clicked
  tap.AssociatedObject = schedulle
  cell.imgSchedulleEdit.addGestureRecognizer(tap)

 return cell
}

func edit(sender: UITapGestureRecognizer) {

   //simulation code getAssociated Object
   let schedulle = sender.getAssociatedObject as Schedulle
}

I know, this is not good, generally i use didSelectRow, but this app needs a click on specific image of cell.

Schedulle have attributes:

import Foundation
import CoreData

class Schedulle: NSManagedObject {

  @NSManaged var createdDate: NSDate
  @NSManaged var message: String
}

Upvotes: 0

Views: 701

Answers (3)

Weles
Weles

Reputation: 1275

According @someGuy and @backsquare, i'll post the complete answer:

I changed for button instead of button.

1 - I defined the protocol, in custom table view cell:

protocol SchedulleEdit : NSObjectProtocol{
  func totalTableViewCellEdit(cell: TotalTableViewCell)
}

2 - i created the var, in custom table view cell to receive the delegate

protocol SchedulleEdit : NSObjectProtocol{
  func totalTableViewCellEdit(cell: TotalTableViewCell)
}

class TotalTableViewCell: UITableViewCell {

  var delegate : SchedulleEdit? = nil
 ...
} 

3 - i defined the function to capture selected cell and send it to the view controller that implement our protocol.

protocol SchedulleEdit : NSObjectProtocol{
  func totalTableViewCellEdit(cell: TotalTableViewCell)
}

class TotalTableViewCell: UITableViewCell {

   var delegate : SchedulleEdit? = nil
  ...
 } 

 @IBAction func edit(sender: UIButton) {
   self.delegate?.totalTableViewCellEdit(self)

 }
}

4 - In ViewController or in TableViewController, depends your case, i implemented the protocol SchedulleEdit:

class TotalViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, SchedulleEdit{
  ...
}

5 - In cellForRowAtIndexPath i set the delegate for:

class TotalViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, SchedulleEdit{

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCellWithIdentifier("cellTotal") as TotalTableViewCell

   cell.delegate = self
   ...
 }

}

6 - Finally i implemented the required method of our protocol:

class TotalViewController: UIViewController,UITableViewDataSource,UITableViewDelegate, SchedulleEdit{

 func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:  NSIndexPath) -> UITableViewCell {
   let cell = tableView.dequeueReusableCellWithIdentifier("cellTotal") as TotalTableViewCell

   cell.delegate = self
   ...
 }

 func totalTableViewCellEdit(cell: TotalTableViewCell) {
   let indexPath = self.tblTotal.indexPathForCell(cell)
   let row = indexPath?.row
   let schedulle = self.schedulleList[row!] as Schedulle
   println(schedulle.message)
 }
}

Upvotes: 0

SomeGuy
SomeGuy

Reputation: 9690

Instead of adding the gesture recognizer in the dequeue cell method, add it in the TotalTableViewCell subclass with the cell as the target, then provide a delegate callback to your view controller, along the lines of totalTableViewCellDidTapImage(cell: TotalTableViewCell)

Now in your view controller you can get the index path for this row by using

func totalTableViewCellDidTapImage(cell: TotalTableViewCell) {
    let indexPath = myTableView.indexPathForCell(cell)
    let schedulle = schedulleList[indexPath.row] as Schedulle
    // do stuff with schedulle
}

Upvotes: 1

kellanburket
kellanburket

Reputation: 12823

Instead of using a UIImageView, use UIButton, and use the button's method setImage(_:forState:) to set your image. Then you can you activate the event using addTarget, which will pass an instance of the button to the action.

Upvotes: 1

Related Questions