How do I capture the point initially tapped in a UIPanGestureRecognizer?
Late to the party, but I notice that nothing above actually answers the question, and there is in fact a way to do this. You must subclass UIPanGestureRecognizer and include:
#import <UIKit/UIGestureRecognizerSubclass.h>
either in the Objective-C file in which you write the class or in your Swift bridging header. This will allow you to override the touchesBegan:withEvent method as follows:
class SomeCoolPanGestureRecognizer: UIPanGestureRecognizer { private var initialTouchLocation: CGPoint! override func touchesBegan(touches: Set<UITouch>, withEvent event: UIEvent) { super.touchesBegan(touches, withEvent: event) initialTouchLocation = touches.first!.locationInView(view) }}
Then your property initialTouchLocation will contain the information you seek. Of course in my example I make the assumption that the first touch in the set of touches is the one of interest, which makes sense if you have a maximumNumberOfTouches of 1. You may want to use more sophistication in finding the touch of interest.
Edit: Swift 5
import UIKit.UIGestureRecognizerSubclassclass InitialPanGestureRecognizer: UIPanGestureRecognizer { private var initialTouchLocation: CGPoint! override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesBegan(touches, with: event) initialTouchLocation = touches.first!.location(in: view) }}
You should be able to use translationInView:
to calculate the starting location unless you reset it in between. Get the translation and the current location of touch and use it to find the starting point of the touch.
@John Lawrence has it right.
Updated for Swift 3:
import UIKit.UIGestureRecognizerSubclassclass PanRecognizerWithInitialTouch : UIPanGestureRecognizer { var initialTouchLocation: CGPoint! override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) { super.touchesBegan(touches, with: event) initialTouchLocation = touches.first!.location(in: view) }}
Note that the instance variable initialTouchLocation
cannot be private, if you want to access it from your subclass instance (handler).
Now in the handler,
func handlePan (_ sender: PanRecognizerWithInitialTouch) { let pos = sender.location(in: view) switch (sender.state) { case UIGestureRecognizerState.began: print("Pan Start at \(sender.initialTouchLocation)") case UIGestureRecognizerState.changed: print(" Move to \(pos)")