Custom UIGestureRecognizer: selector does not receive UIGestureRecognizerStateBegan

I am using a custom UIGestureRecognizer. For simplicity, suppose that it recognizes a gesture consisting of> 1 touches.

Here is Gesture.m:

#import "Gesture.h" #import <UIKit/UIGestureRecognizerSubclass.h> #define SHOW printf("%s %d %d %d\n", __FUNCTION__, self.state, touches.count, self.numberOfTouches) @implementation Gesture - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event { SHOW; if (self.numberOfTouches==1) return; self.state = UIGestureRecognizerStateBegan; } - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event { SHOW; if (self.numberOfTouches==1) return; self.state = UIGestureRecognizerStateChanged; } - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event { SHOW; if (self.numberOfTouches==1) return; self.state = UIGestureRecognizerStateEnded; } @end 

Here is the selector:

 - (IBAction)handleGesture:(Gesture *)recognizer { printf("%s %d\n", __FUNCTION__, recognizer.state); } 

And here is the conclusion:

 -[Gesture touchesBegan:withEvent:] 0 1 1 // 1st touch began -[Gesture touchesMoved:withEvent:] 0 1 1 -[Gesture touchesMoved:withEvent:] 0 1 1 -[Gesture touchesMoved:withEvent:] 0 1 1 -[Gesture touchesBegan:withEvent:] 0 1 2 // 2nd touch began -[Gesture touchesMoved:withEvent:] 1 1 2 // Gesture.state==UIGestureRecognizerStateBegan but selector was not called -[ViewController handleGesture:] 2 // UIGestureRecognizerStateChanged received. -[Gesture touchesMoved:withEvent:] 2 2 2 -[ViewController handleGesture:] 2 -[Gesture touchesMoved:withEvent:] 2 2 2 -[ViewController handleGesture:] 2 -[Gesture touchesMoved:withEvent:] 2 2 2 -[ViewController handleGesture:] 3 // UIGestureRecognizerStateEnded received. 

Why doesn't the selector get a UIGestureRecognizerStateBegan?

+4
source share
1 answer

This was not particularly obvious to me, but the rules seemed to be:

  • all touches sent to you through touchesBegan:... are subsequently deemed to be yours if and until you set the status to UIGestureRecognizerStateFailed , UIGestureRecognizerStateEnded or UIGestureRecognizerStateCancelled ;
  • If you switch to UIGestureRecognizerStateBegan , then the gesture recognizer will publish it, then it will automatically generate UIGestureRecognizerStateChanged when the bindings that are now assigned to you move.

Thus, you should not set UIGestureRecognizerStateChanged for yourself - just follow the touches and send the message correctly, finish, fail and cancel.

In your case, I think you just need to remove the state in touchesMoved:...

(otherwise: the above applies to iOS 5 and 6, and under 4 it’s a little more subtle. To work in all three versions, use a construct like if(self.state == UIGestureRecognizerStateBegan) self.state = UIGestureRecognizerStateChanged; when you know that your properties have changed)

+3
source

Source: https://habr.com/ru/post/1433171/


All Articles