David David - 5 months ago 51
Swift Question

UIScreenEdgePanGestureRecognizer is triggering multiple times

I'm using the following code for going back and forward in my WebView with

UIScreenEdgePanGestureRecognizer
:

class FirstViewController: UIViewController {

@IBOutlet var homewebview: UIWebView!

// create left edge and right edge gesture
let leftEdgePanGesture = UIScreenEdgePanGestureRecognizer()
let rightEdgePanGesture = UIScreenEdgePanGestureRecognizer()


override func viewDidLoad() {
super.viewDidLoad()

// add target for gesture
self.leftEdgePanGesture.addTarget(self, action: #selector(FirstViewController.handleLeftEdge(_:)))
self.rightEdgePanGesture.addTarget(self, action: #selector(FirstViewController.handleRightEdge(_:)))

// set detection edge
self.leftEdgePanGesture.edges = UIRectEdge.Left
self.rightEdgePanGesture.edges = UIRectEdge.Right

// add gesture into view
self.view.addGestureRecognizer(self.leftEdgePanGesture)
self.view.addGestureRecognizer(self.rightEdgePanGesture)
}
func handleLeftEdge( gesture: UIScreenEdgePanGestureRecognizer ) {
homewebview.goBack()
}

// perform operation when right edge gesture detected
func handleRightEdge( gesture: UIScreenEdgePanGestureRecognizer ) {
homewebview.goForward()
}
}


My problem is that it's triggering multiple times. It doesn't go back/forward one webpage, it goes back/forward ca. 5 webpages.

Is there any solution? Or will I have to use
UISwipeGestureRecognizer
. I rather don't want to use
UISwipeGestureRecognizer
because it doesn't react as reliable as
UIScreenEdgePanGestureRecognizer
.
UISwipeGestureRecognizer
sometimes "thinks" I want to scroll vertically in my WebView and doesn't react. Or is there a solution for this?

Answer

The pan gesture recognizer calls the handler method any time its state changes. That includes when it starts, ends, and every movement in between. Inside the handler, you need to check the gesture recognizer's state and decide what to do.

You want to trigger your code only once per gesture, and you want to do it only when the touch has moved more than a threshold amount.

class ViewController: UIViewController {

    let leftEdgePanGesture = UIScreenEdgePanGestureRecognizer()
    var leftPanTriggered: Bool = false

    override func viewDidLoad() {
        super.viewDidLoad()

        leftEdgePanGesture.addTarget(self, action: #selector(handleLeftEdge(_:)))
        leftEdgePanGesture.edges = .Left
        view.addGestureRecognizer(leftEdgePanGesture)
    }

    func handleLeftEdge(gesture: UIScreenEdgePanGestureRecognizer) {
        switch gesture.state {
            case .Began, .Changed:
                if !leftPanTriggered {
                    let threshold: CGFloat = 10  // you decide this
                    let translation = gesture.translationInView(view).x
                    if translation >= threshold  {
                        performLeftGesture()
                        leftPanTriggered = true
                    }
                }

            case .Ended, .Failed, .Cancelled:
                leftPanTriggered = false

            default: break
        }
    }

    func performLeftGesture() {
        homewebview.goBack()
    }

}
Comments