-1

I have a tableView with cells. Each cell has an imageView. When I click on the imageView, I want to execute a function with parameters that I pass in. The only way that I know how to work with clicking on imageViews is something like this:

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printNumber))
cell.imageView.addGestureRecognizer(gestureRecognizer)

@objc func printNumber(){
        print("4")
}

Now, imagine this exact same thing, but I want to pass the number to print into the function I've seen a million different posts about how you can't pass parameters into selectors, so I'm not sure what to do in this case.

I want to do something like this (I know you can't do this)

let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printNumber(num: 4))
cell.imageView.addGestureRecognizer(gestureRecognizer)

@objc func printNumber(String: num){
        print(num)
}

I need to do this because every button will have a different output when pressed, depending on some other variables in the cell.

Cœur
  • 37,241
  • 25
  • 195
  • 267
Evan
  • 1,892
  • 2
  • 19
  • 40
  • 1
    are you looking for this? https://stackoverflow.com/questions/38445262/pass-parameter-with-uitapgesturerecognizer – Don Jan 07 '20 at 00:09
  • O damn that actually might be it, I'll check it out when I get home, thanks mate! – Evan Jan 07 '20 at 00:12

2 Answers2

0

You don't need to pass in the number. Assuming the recognizer is on the image view you:

  1. Get the gestures.view (this is the image view)
  2. Walk up the responder chain to find the parent tableview cell and table view
  3. Ask the tableview for the index path of the tableview cell (this is basically he number you wanted to pass in)
  4. Call your function with the number

As for walking up the responder chain generically:

extension UIResponder {
    func firstParent<Responder: UIResponder>(ofType type: Responder.Type ) -> Responder? {
        next as? Responder ?? next.flatMap { $0.firstParent(ofType: type) }
    }
}

so your code is:

  guard let cell = recognizer.view?.firstParent(ofType: UITableViewCell.self),
     let tableView = recognizer.view?.firstParent(ofType: UITableView.self),
     let indexPath = tableview.indexPath(for: cell) else {
    return
  }
  // Do stuff with indexPath here
Josh Homann
  • 15,933
  • 3
  • 30
  • 33
  • Hmm thank you, I think I see what youre saying, could you write an example like for the example I gave, printing out the index path number of the cell where the button is pressed? – Evan Jan 06 '20 at 23:59
0

Use the accessibilityIdentifier property, only if you still want to use the #selector, so that UIGestureRecognizer can read the value of the value object.

 func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath) as! YourTableViewCell
    …
    let gestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(printNumber))
    cell.imageView.accessibilityValue = String(4)
    cell. imageView.isUserInteractionEnabled = true
    cell.imageView.addGestureRecognizer(gestureRecognizer)
    …
    return cell
 }

 @objc func printNumber(sender: UITapGestureRecognizer) {
        if let id = sender.view?.accessibilityIdentifier {
            print(tag)
        }
 }
El Tomato
  • 6,479
  • 6
  • 46
  • 75