UIPanGestureRecognizer 获取开始和停止之间的长度

UIPanGestureRecognizer get the length between start and stop

这是我的代码:

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

这里是 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);

    }   
}

我想使用这个长度,但它显示错误:常数 'startLocation' 在初始化之前使用。

如果我将其更改为:

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);
    }
}

它将显示:使用未解析的标识符 'startLocation'。 (P.s:我已经尝试过使用 switch 和 case ,它显示了同样的问题) 有人可以帮我解决这个问题吗? 提前致谢。

问题是每次更新手势时都会调用 handlePanRecognizer(),所以当手势结束时,您没有 startLocation,因为它是在处理程序方法的另一个调用中设置的。

您应该将最后一个位置存储为可选 属性:

var startPanLocation: CGPoint?

现在在.began情况下设置它并用它来计算在.ended情况下的距离:

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
    }
}

顺便说一句,如果变量已定义但未初始化,则不能使用该变量:

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

这里有三个问题。

首先,let用于定义一个const变量,或者说一旦创建就不会改变的变量。您的第一段代码失败是因为您试图在 startLocation 创建为空 CGPoint 后更改它的值,如果您将 let 更改为 var,你应该没事。

其次,下一段代码存在作用域问题。任何时候你使用 { },你都会创建一个新的范围,它可以访问范围外的所有变量,并且可以在范围内创建新变量。一旦该范围以右大括号结束,在其中创建的所有内容都会被销毁,包括您的 let startLocation,这就是为什么 else if 范围看不到它的原因。

最后,作用域问题也适用于整个函数,每次调用 respondsToPanGesture(sender:) 方法时,都会创建一个全新的 startLocation,并且它之前的所有实例都会被摧毁。如果你想在调用之间维护这个值,你需要在 class 本身中创建 startLocation,并在函数中更新它。

class MyClass
{
  var startLocation = CGPoint.zero

  func respondsToPenGesture(sender: UIPanGestureRecognizer) 
  {
    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);
    }   
  }
}

希望对您有所帮助:-)