Search code examples
iosswiftpositionuipangesturerecognizer

UIPanGestureRecognizer get the length between start and stop


This is my code :

override func viewDidLoad() {
    super.viewDidLoad()
    let panRecognizer = UIPanGestureRecognizer(target: self, action: #selector(PreviewViewController.respondsToPenGesture))
    self.view.addGestureRecognizer(panRecognizer)}

Here blow is the respondsToPenGesture Func:

func respondsToPenGesture(sender: UIPanGestureRecognizer) {
    let startLocation : CGPoint
    if (sender.state == UIGestureRecognizerState.Began) {
        startLocation = sender.locationInView(self.newEffectView)
    }
    else if (sender.state == UIGestureRecognizerState.Ended) {

        let stopLocation = sender.locationInView(self.newEffectView)

        let dx = stopLocation.x - startLocation.x;
        let dy = stopLocation.y - startLocation.y;
        let distance = sqrt(dx*dx + dy*dy );
        NSLog("Distance: %f", distance);

    }   
}

I want to use this length,and it shows error : Constant 'startLocation' used before being initialized.

And if I change it to :

func respondsToPenGesture(sender: UIPanGestureRecognizer) {
    //let startLocation : CGPoint
    if (sender.state == UIGestureRecognizerState.Began) {
        let startLocation = sender.locationInView(self.newEffectView)
    }
    else if (sender.state == UIGestureRecognizerState.Ended) {

        let stopLocation = sender.locationInView(self.newEffectView)

        let dx = stopLocation.x - startLocation.x;
        let dy = stopLocation.y - startLocation.y;
        let distance = sqrt(dx*dx + dy*dy );
        NSLog("Distance: %f", distance);
    }
}

It will show : Use of unresolved identifier 'startLocation'. (P.s: i already tried with use switch and case , it shows the same problem) Someone can help me with this problem ? Thx in advance .


Solution

  • The problem is that handlePanRecognizer() is called every time the gesture is updated, so when the gesture ends, you don't have the startLocation because it was set in another call of the handler method.

    You should store last location as an optional property:

    var startPanLocation: CGPoint?
    

    Now set it in .began case and use it to calculate the distance in .ended case:

    func handlePanRecognizer(panRecognizer: UIPanGestureRecognizer) {
        let currentLocation = panRecognizer.location(in: self.newEffectView)
    
        switch panRecognizer.state {
        case .began:
            startPanLocation = currentLocation
        case .ended:
            let dx = currentLocation.x - startPanLocation.x;
            let dy = currentLocation.y - startPanLocation.y;
            let distance = sqrt(dx*dx + dy*dy );
            startPanLocation = nil
        default: break
        }
    }
    

    Btw, you cannot use the variable if it was defined but not initialized:

    let startLocation : CGPoint      //defined
    let startLocation = CGPoint.zero //initialized