7

I have made a view clickable with a tap gesture recognizer, which is working just fine. But I want to highlight the view when the touch happens en remove it when the touch ended.

I have tried this:

- (IBAction)refresh:(UITapGestureRecognizer *)sender {
    if(self.currentStatus == NODATA){
        if(sender.state == UIGestureRecognizerStateBegan){
            NSLog(@"Began!");
            [self.dashboardViewController.calendarContainer state:UIViewContainerStatusSELECTED];
        }
        if (sender.state == UIGestureRecognizerStateEnded){
             NSLog(@"%@", @"Ended");
            [self.dashboardViewController.calendarContainer state:UIViewContainerStatusNORMAL];
        } 
        [self setState:REFRESHING data:nil];
    }
}

The NSLog of "Ended does" get displayed but the began didn't so it never goes into selected. Why is this?

Bertrand Caron
  • 2,525
  • 2
  • 22
  • 49
Haagenti
  • 7,974
  • 5
  • 38
  • 52

5 Answers5

14

UITapGestureRecognizer will never go in the UIGestureRecognizerStateBegan state. Only continuous gestures (such as a swipe or a pinch) will result for their recognizers going from UIGestureRecognizerStatePossible to UIGestureRecognizerStateBegan. Discrete gestures, such as a tap, put their recognizers directly into UIGestureRecognizerStateRecognized, i.e. for a single tap, right into UIGestureRecognizerStateEnded.

That said, maybe you're looking for a UILongPressGestureRecognizer, which is a continuous recognizer that will enter UIGestureRecognizerStateBegan, allowing you to discern beginning and end of touch?

triazotan
  • 2,192
  • 1
  • 22
  • 32
5

It might be too late. But this will also help you, if you strictly want to use Gesture recognizer.

   UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc]
                                         initWithTarget:self 
                                         action:@selector(refresh:)];
    longPress.minimumPressDuration = 0.0;

 - (IBAction)refresh:(UILongPressGestureRecognizer *)sender {
     if(self.currentStatus == NODATA){
       if(sender.state == UIGestureRecognizerStateBegan){
         NSLog(@"Began!");
         [self.dashboardViewController.calendarContainer state:UIViewContainerStatusSELECTED];
       }
       if (sender.state == UIGestureRecognizerStateEnded){
         NSLog(@"%@", @"Ended");
        [self.dashboardViewController.calendarContainer state:UIViewContainerStatusNORMAL];
       } 
       [self setState:REFRESHING data:nil];
    }
   }
Mavericks
  • 524
  • 3
  • 5
2

You can also use touchesBegan:withEvent: and touchesEnded:withEvent: methods.

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *t = [event touchesForView:_myView];
    if([t count] > 0) {
        // Do something 
    }
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    NSSet *t = [event touchesForView:_myView];
    if([t count] > 0) {
        // Do something
    }
}
juniperi
  • 3,723
  • 1
  • 23
  • 30
1

Swift 4.2

let recognizer = UILongPressGestureRecognizer(target: self, action: Selector("touched:"))
recognizer.delegate = self
recognizer.minimumPressDuration = 0.0
addGestureRecognizer(recognizer)
userInteractionEnabled = true

/**
 * Gesture handler
 */   
@objc func touched(sender: UILongPressGestureRecognizer) {
    if sender.state == .began {
        /*onPressed*/
    } else if sender.state == .ended {
        /*onReleased*/
    }
}
Sentry.co
  • 5,355
  • 43
  • 38
0

Quite an old question, but still. Hope it will be helpful for somebody. If I've got the author's question right, the idea is to detect whether the tap has began recognizing and to perform an action. Like if you don't want target to trigger only when the user releases the finger but already when he touch it for the very first time.

An easy way to do so is to make an extension for UITapGestureRecognizer like below:

fileprivate class ModTapGestureRecognizer: UITapGestureRecognizer {
    
    var onTouchesBegan: (() -> Void)?
    
    override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent) {
        onTouchesBegan?()
        super.touchesBegan(touches, with: event)
    } 
}

Later in your code you can use it like so:

let tapRecognizer = ModTapGestureRecognizer()
tapRecognizer.addTarget(self, action: #selector(didTapped))
tapRecognizer.onTouchesBegan = {
   print("Yep, it works")
}
yourView.addGestureRecognizer(tapRecognizer)

And you're awesome!

grigorevp
  • 631
  • 6
  • 13