Search code examples
iosswiftuipangesturerecognizer

UIPanGestureRecognizer handler crashes my applications - swift


I have an application that contains a UIImageView. I have drawn a small circle in a subview of the parent UIImageView. I would like the user to be able to touch and drag the small blue circle within the main UIImageView. I have set up a UIPanGestureRecognizer for this child view. I am trying to test if my handler for the UIPanGestureRecognizer is being fired, but as I touch and drag on the main UIImageView, my app crashes with the following error:

Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[UIView firstDotHandlerWithSender:]: unrecognized selector sent to instance 0x103507d80'

Swift:

var firstDotView: UIView?
@IBOutlet weak var imgView: UIImageView!

override func viewDidLoad() {
    super.viewDidLoad()

    firstDotView = UIView.init()
    firstDotView?.frame = imgView.bounds
    imgView.addSubview(firstDotView!)

    // DRAW A FILLED IN BLUE CIRCLE
    drawBlueCircle()

    imgView.isUserInteractionEnabled = true
    firstDotView?.isUserInteractionEnabled = true

    // ADD GESTURE RECOGNIZER
    let firstDotPanRecgnzr = UIPanGestureRecognizer.init(target: firstDotView!, action: #selector(firstDotHandler(sender:)))
    firstDotView?.addGestureRecognizer(firstDotPanRecgnzr)
}


@objc func firstDotHandler(sender: UIPanGestureRecognizer) -> Void {

    print("translation ...")

    let firstDot = sender.view
    let translation = sender.translation(in: view)

    if(sender.state == .began || sender.state == .changed){
        firstDot?.center = CGPoint.init(x: (firstDot?.center.x)! + translation.x, y: (firstDot?.center.y)! + translation.y)
        sender.setTranslation(CGPoint.zero, in: self.view)
    }
}

func drawBlueCircle(){
    let layer = CAShapeLayer()
    layer.path = UIBezierPath.init(roundedRect: CGRect.init(x: 60, y: 60, width: 30, height: 30), cornerRadius: 50).cgPath
    layer.fillColor = UIColor.blue.cgColor
    firstDotView?.layer.addSublayer(layer)
}

Solution

  • The target for your UIPanGestureRecognizer is wrong.

    let firstDotPanRecgnzr = UIPanGestureRecognizer(target: self, action: #selector(firstDotHandler(sender:)))
    

    target tells the pan gesture where your selector is located. I think you confused it to be which element it is supposed to act on. (I made the same mistake when i was new :D)


    From the docs.

    target

    An object that is the recipient of action messages sent by the receiver when it recognizes a gesture. nil is not a valid value.