7

I have a UIView with 2 subviews, let's call it view A:

  • a basic UIView, called B
  • a UIScrollView, called C

I overrided the following method in view A:

  • - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
  • - (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event

When I touch view B, touchesBegan:withEvent: and touchesEnded:withEvent: get called, but if I touch the UIScrollView (view C), there are not called.

I know this is the expected behaviour, but I am trying to understand why. I could not find any clear answer on that. Any idea?

MartinMoizard
  • 6,600
  • 12
  • 45
  • 75

5 Answers5

9

Use the TapGestureRecognizer instead of touchBegan method

UITapGestureRecognizer *singleTapGestureRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(singleTap:)];
singleTapGestureRecognizer.numberOfTapsRequired = 1;
singleTapGestureRecognizer.enabled = YES;
singleTapGestureRecognizer.cancelsTouchesInView = NO;
[scrollView addGestureRecognizer:singleTapGestureRecognizer];

- (void)singleTap:(UITapGestureRecognizer *)gesture {  
//handle taps   
}

Swift version :

let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: "singleTap:")
    singleTapGestureRecognizer.numberOfTapsRequired = 1
    singleTapGestureRecognizer.enabled = true
    singleTapGestureRecognizer.cancelsTouchesInView = false
    scrollViewH.addGestureRecognizer(singleTapGestureRecognizer)

func singleTap(sender: UITapGestureRecognizer) {
    println("handle taps ")

}
Lilo
  • 2,724
  • 25
  • 16
7

if you have scroll view thouchesBegan method will not work because if want scrolling you have to Enable userInteractionEnabled to YES in storyboard. If you make it to NO it'll trigger. So solution is use TapGestureRecognizer Add this to your viewDidLoad:

let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: "MyTapMethod:")
    singleTapGestureRecognizer.numberOfTapsRequired = 1
    singleTapGestureRecognizer.enabled = true
    singleTapGestureRecognizer.cancelsTouchesInView = false
    myscrollView.addGestureRecognizer(singleTapGestureRecognizer)

Then add this MyTapMethod in your controller.

func MyTapMethod(sender: UITapGestureRecognizer) {
        //NSLog("touchesBegan")
        self.view.endEditing(true)
    }

This is working fine.

Anushka Madushan
  • 681
  • 2
  • 12
  • 31
6

You have at least 2 options:

1) "By setting userInteractionEnabled to NO for your scroll view". More info here https://stackoverflow.com/a/25108078/1702413

2) subclass your UIScrollView - for example with this https://dl.dropboxusercontent.com/u/19438780/ClassScrollViewDelegate.zip

UPDATE

Why? Please, read again the documentation:

"Because a scroll .. it must know whether a touch signals an intent to scroll ... it temporarily intercepts a touch-down event ... .. the scroll view cancels any tracking in the subview and performs the scrolling itself"

And most important: **

Subclasses can override the touchesShouldBegin:withEvent:inContentView:, pagingEnabled, and touchesShouldCancelInContentView: methods

From here: https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIScrollView_Class/index.html#//apple_ref/doc/uid/TP40006922

Community
  • 1
  • 1
TonyMkenu
  • 7,597
  • 3
  • 27
  • 49
  • 1
    I am not looking for solutions, I am looking to understand why touchesBegan is not called when I touch the UIScrollView – MartinMoizard Mar 05 '15 at 14:58
4

Swift 3/4 version:

let singleTapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(MyViewController.tapRecognized))
singleTapGestureRecognizer.numberOfTapsRequired = 1
singleTapGestureRecognizer.isEnabled = true
singleTapGestureRecognizer.cancelsTouchesInView = false
scrollView.addGestureRecognizer(singleTapGestureRecognizer)

And then:

@objc func tapRecognized() {
    view.endEditing(true)
}
jonaszmclaren
  • 2,459
  • 20
  • 30
0

Please check this to recognize touch events(began,moved,ended) using pan gesture of the scrollview,

Class CustomScrollView:UIScrollView
{

CustomScrollView()
{

 (this.GestureRecognizers[1] as UIPanGestureRecognizer).AddTarget(() => this.PanHandle(this.GestureRecognizers[1] as UIPanGestureRecognizer));
    

}


 private void PanHandle(UIPanGestureRecognizer gestureRecognizer)
          
  {
  var touchLocation=gestureRecognizer.LocationInView(this)
    
       

  if (gestureRecognizer.State == UIGestureRecognizerState.Began)
            
    {
             
      //Touches began
             
   }
     
else if (gestureRecognizer.State == UIGestureRecognizerState.Changed)
            
   {
           
        //Touches Moved
             
   }
               
 else if (gestureRecognizer.State == UIGestureRecognizerState.Ended)
         
       {
             
       //Touches ended
              
  }
           
 }

    }

Regards,
Ashwin
Ashwin Kmr
  • 280
  • 1
  • 7
  • 20