Question

I need to catch two different swipping gestures using UISwipeGestureRecognizer(for example, UISwipeGestureRecognizerDirectionRight and UISwipeGestureRecognizerDirectionLeft). When I add two different recognisers with addGestureRecognizer method, only last added recognizer works. I've read that I need to implement gestureRecognizer:shouldRecognizeSimultaneouslyWithGestureRecognizer: method of UIGestureRecognizerDelegate protocol, but nothing works.

Can anyone help with simple example of catching two or more same gestures? Thanks!

Was it helpful?

Solution

It was really easy:

At first we should create class, that implements UIGestureRecognizerDelegate protocol:

@interface MyGestureDelegate : NSObject <UIGestureRecognizerDelegate>

@implementation MyGestureDelegate

- (BOOL)gestureRecognizerShouldBegin:(UIGestureRecognizer *)gestureRecognizer{
    return YES;
}

- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldRecognizeSimultaneouslyWithGestureRecognizer:(UIGestureRecognizer *)otherGestureRecognizer{
    return YES;
}
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch{
    return YES;
}

And use it like this:


    UISwipeGestureRecognizer *swipeGestureLeft = [[UISwipeGestureRecognizer alloc]
                                              initWithTarget:self action:@selector(handleSwipeGestureLeft:)];
    [self.view addGestureRecognizer:swipeGestureLeft];
    swipeGestureLeft.direction = UISwipeGestureRecognizerDirectionLeft;
    [swipeGestureLeft release];

    UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]
                                          initWithTarget:self action:@selector(handleSwipeGesture:)];
    swipeGesture.direction = UISwipeGestureRecognizerDirectionRight;
    [self.view addGestureRecognizer:swipeGesture];

    MyGestureDelegate *deleg = [[MyGestureDelegate alloc] init];

    [swipeGesture setDelegate:deleg];
    [swipeGesture release];

OTHER TIPS

The answer: "Um, a quick look at the documentation..." from Phoenix absolutely will not work!

He is setting a mask, then using the same variable to test as if the recognizer cleared it and set a single bit. It stores, as he correctly quoted from the documentation:

The permitted directions of the swipe

sender.direction

will simply return the mask you set initially and in his example, will never resolve to a single direction!

UISwipeGestureRecognizerDirectionRight == 1
UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft == 3

Additionaly, for most cases you don't need to:

  • setup a delegate
  • permit simultaneous gesture recognition (unless you want simultaneous swipes; not likely)
  • send the recognizer to the selector

The following works for me:

   UISwipeGestureRecognizer* swipe;

   swipe = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeL)] autorelease];
   swipe.direction = UISwipeGestureRecognizerDirectionLeft;
   [view addGestureRecognizer:swipe];

   swipe = [[[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(handleSwipeR)] autorelease];
   swipe.direction = UISwipeGestureRecognizerDirectionRight; // default
   [view addGestureRecognizer:swipe];

Um, a quick look at the documentation would reveal that you are doing way more work than you need to:

"direction The permitted directions of the swipe.

@property(nonatomic) UISwipeGestureRecognizerDirection direction

Discussion You may specify multiple directions by specifying multiple UISwipeGestureRecognizerDirection constants using bitwise-OR operands. The default direction is UISwipeGestureRecognizerDirectionRight."

Which is to say, instead of using two UISwipeGestureRecognizers, you can just do the following:

UISwipeGestureRecognizer *swipeGesture = [[UISwipeGestureRecognizer alloc]
                                      initWithTarget:self action:@selector(handleSwipeGesture:)];

 swipeGesture.direction = UISwipeGestureRecognizerDirectionRight | UISwipeGestureRecognizerDirectionLeft;

And in your action method:

  -(IBAction)handleSwipeGesture:(UISwipeGestureRecognizer*)sender
     {
     if (sender.direction == UISwipeGestureRecognizerDirectionLeft) {

         //do left action

     } else {

         //do right action

     }
}

Much simpler, and much less prone to conflict.

I would suggest you read a little bit on the technique that the gesture recognizers use to recognize the gesture. I suppose, the first recognizer tries to recognize the gesture, but realizes that he does not has to respond to it and then somehow he does not pass it on.

It's very useful to read how they work in order to understand how to use them.

Hope this helps.

Thanks to user294890's suggestion, I was successful by returning yes from the listed UIGestureRecognizerDelegate methods.

I found however that it would not work when I was adding the GestureRecognizer before the web view had loaded. It did however work when I added the GestureRecognizer to the webView in the webView delegate method:

- (void)webViewDidFinishLoad:(UIWebView *)webView.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top