Acorn
Acorn

Reputation: 1165

Pass selector from UIViewController to UIView

I've created a custom class that inherits from UIView, BlueView. I have a method in my UIViewController that I want to have called when BlueView is tapped by the user. However, my program crashes whenever I tap the BlueView with this exception:

2019-09-15 23:06:14.960704-0400 DoubleViewApp[2418:70709] -[DoubleViewApp.BlueView handleBlueTapWithSender:]: unrecognized selector sent to instance 0x7f820cd06790

UIView:

import UIKit

class BlueView: UIView {

  override init(frame: CGRect) {
    super.init(frame: frame)
    createSubview()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    createSubview()
  }

  func createSubview() {
    print("createSubview from BlueView")
    backgroundColor = .blue

    let tap = UITapGestureRecognizer(target: self, action: #selector(handleTap(sender:)))
    addGestureRecognizer(tap)
  }

  func setTapGesture(action: Selector?) {
    let tap = UITapGestureRecognizer(target: self, action: action)
    addGestureRecognizer(tap)
  }

  @objc func handleTap(sender: UITapGestureRecognizer? = nil) {
    print("NO! DO NOT TAP THE BLUE SQUARE.")

  }

}

ViewController:

import UIKit

class ViewController: UIViewController {


  override func viewDidLoad() {
    super.viewDidLoad()
    print("Hello World")
    // Do any additional setup after loading the view.
    let bview = BlueView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
    let rview = RedView(frame: CGRect(x: 0, y: 300, width: 300, height: 300))
    view.addSubview(bview)
    view.addSubview(rview)

    bview.setTapGesture(action: #selector(handleBlueTap(sender:)))
  }


  @objc func handleBlueTap(sender: UITapGestureRecognizer? = nil) {
    print("This is a funny message.")
    //Todo: Present new ViewController
  }
}

Upvotes: 0

Views: 526

Answers (1)

Chris Zielinski
Chris Zielinski

Reputation: 1391

You also have to set the correct target for the selector. At the moment, you are setting the target as the BlueView instance, but you want it to be the view controller.

class BlueView: UIView {

    ...

    func setTapGesture(target: Any?, action: Selector?) {
        addGestureRecognizer(UITapGestureRecognizer(target: target, action: action))
    }

    ...

}

& then you can use:

bview.setTapGesture(target: self, action: #selector(handleBlueTap(sender:)))

Upvotes: 2

Related Questions