Hi,
I'd like to handle touches (horizontal slide in particular) in a UIViewController subclass I did, but the problem is the controller's view contains a UIScrollView which covers the whole screen, so "touchesBegan:" and "touchesEnded:" events are never called in my controller. The scrollview only scrolls vertically.
What would be the best way to make it able to handle these events? Make my UIViewController also inherit from UIScrollView and handle touches as needed (and remove the current scroll view), or use a UIScrollView subclass in place of my current scroll view, which will call a delegate method for the cases I need? Or maybe is there a another way?
Here is my current code:
// View creation and adding to parent
NewViewController* newViewController = [[newViewController alloc] initWithNibName:@"NewViewController" bundle:nil];
[self.view addSubview:newViewController.view];
// NewViewController.h
@interface NewViewController : UIViewController {
IBOutlet UIScrollView* scrollView;
// other outlets and properties
}
- (void)touchesBegan:(NSSet*)touches withEvent:(UIEvent*)event;
- (void)touchesEnded:(NSSet*)touches withEvent:(UIEvent*)event;
In IB, NewViewController's view contains scrollView which contains all other outlets (labels, buttons)... The goal would be to get NewViewController's scrollView to call NewViewController's touchesBegan and touchesEnded methods.
Update: The ScrollViewSuite helped me a lot to understand how the touches callbacks are handled. UIScrollView
only calls them when the touches don't make it scroll.
So, three cases:
- Oblique slide (even slightly, as soon as scrollbar appears): no
touches
method is called - Perfectly horizontal slide (no scrollbar appears):
touchesBegan
,touchesMoved
andtouchesEnded
are called - Any touch that doesn't cause a scroll (touch without moving, or horizontal move) followed by a slightly vertical slide:
touchesBegan
,touchesMoved
andtouchesCancelled
are called;
Touches cancel can be avoided by setting the UIScrollView
's canCancelContentTouches
to FALSE
but this obviously only works if touchesBegan
has been called, which means touches methods will still not be called for the first case.
But UIScrollView
has a property called delaysContentTouches which is set at TRUE
by default, and causes it to wait a little bit when a touch begins in order to see if it will make him scroll. If this is set to FALSE
, touches methods are called as soon as the touch starts and allows a subclasses to handle them as they wish.
TL;DR: What seems to be the easiest way to me (if you can't use UIGestureRecognizer
) is to subclass UIScrollView
, set its delayContentTouches
property to FALSE
and override touches functions (touchesShouldBegin
/ touchesShouldCancel
as well as touchesBegan
/ touchesMoved
...) according to your needs.