Lars Petersen
Lars Petersen

Reputation: 622

How can I find out when a pinch gesture is finished (UIGestureRecognizer)

I want to get a callback when my UIPinchGestureRecognizer finished a pinch-gesture. Moreover it would be great to know if the finished gesture was a zoom in or a zoom out.

Does anyone know a method to use? Or the approach to do?

Thanks!

Upvotes: 10

Views: 3433

Answers (4)

Derek Lee
Derek Lee

Reputation: 3660

For some reason, I am not consistently receiving a pinch gesture recognizer state of .ended when testing on my devices. I've managed to get this to trigger once in awhile, but it is wildly inconsistent.

(I wonder if it is because I have a pinch gesture recognizer attached to a UICollectionView, but I haven't tried it with other views to confirm. For this reason, I don't think overriding touchesEnded is a solution that I can consider since other touch events/gestures are being used.)

The most consistent check I could perform was to confirm the number of touches on the gesture recognizer.

Assuming you have attached a pinch gesture recognizer to a view:

let pinchGesture = UIPinchGestureRecognizer(target: self, action: #selector(didReceivePinchGesture))
yourView.addGestureRecognizer(pinchGesture)

Inside the handler, I check the number of touches to ensure that it is a pinch gesture. If it is not two, then I can deduce that this is the end of the gesture:

@objc func didReceivePinchGesture(_ gestureRecognizer: UIPinchGestureRecognizer) {
    guard gestureRecognizer.numberOfTouches == 2 else {
        // Logic for pinch gesture ended
        return
    }

    if gestureRecognizer.state == .began {
        ...
    } else if gestureRecognizer.state == .changed {
        ...
    } else {
        // Same logic for pinch gesture ended (though rarely invoked)
    }
}

Caveat: When testing this, similar to how the .ended state does not get triggered if you don't lift your fingers at exactly the same millisecond, it appears as though the gesture recognizer is called even when there's only one touch at the beginning if your fingers do not touch the screen at the exact same time.

I have explicit logic to begin processing the gesture when the state equals .began so this didn't have any negative impacts on my logic. However, depending on what you are trying to accomplish this may be a concern for you.

Upvotes: 0

Lemont Washington
Lemont Washington

Reputation: 556

The best approach which does not require subclassing is to examine the "state" property on the gesture recognized instance in your action handler. The state will change during all phases of the lifecycle of the gesture. The state change you're looking for is UIGestureRecognizerStateEnded. It is also good practice to check for UIGestureRecognizerStateCancelled as well.

Upvotes: 0

cahlbin
cahlbin

Reputation: 1069

Another approach instead of overriding touchesEnded:, is that you could just check the state of the gesture recognizer in your target handler method.

  -(void)handlePinchGesture:(UIGestureRecognizer*)gestureRecognizer {    
    if(UIGestureRecognizerStateEnded == [gestureRecognizer state]){
      // do something
    }
  }

Upvotes: 14

tadejsv
tadejsv

Reputation: 2092

You can know if it was a zoom in or out by the scale property of the UIPinchGestureRecognizer.

Just overrride it's touchesEnded: method to get a callback (and the call some other method if you wish).

Upvotes: 1

Related Questions