I have a subclassed UIView
that implements touchesBegan, touchesMoved, touchesEnded
. All is working well. Then, I added a UIScrollview
as subview to this UIVIew
. Touches made within the UIScrollview
are not forwarded back up the responder chain to the parent view, and so my UIView's touch methods are never called (they are called for touches made outside of the scrollview just fine).
I created a new UIScrollView category like so:
@implementation UIScrollView (forwardTouches)
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
// If not dragging, send event to next responder
if (!self.dragging){
[self.nextResponder touchesBegan: touches withEvent:event];
[self setScrollEnabled:NO];
NSLog(@"touchesBegan");
}
else{
NSLog(@"touchesBegan-else");
[super touchesEnded: touches withEvent: event];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
// If not dragging, send event to next responder
if (!self.dragging){
[self.nextResponder touchesMoved: touches withEvent:event];
NSLog(@"touchesMoved");
}
else{
NSLog(@"touchesMoved - else");
[super touchesEnded: touches withEvent: event];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// If not dragging, send event to next responder
if (!self.dragging){
[self.nextResponder touchesEnded: touches withEvent:event];
[self setScrollEnabled:YES];
NSLog(@"touchesEnded");
}
else{
NSLog(@"touchesEnded - else");
[super touchesEnded: touches withEvent: event];
}
}
This actually seems to work as intended on the iPhone (which would be: if the user drags his finger across the scrollview, it scrolls, but if he places it on the view and does not move it, the parent view's touchesBegan method fires), but it does not work on the iPad. Presumably, self.dragging
needs more time on the iPad, but I'm struggling to figure out a way to solve this reliably. I'm sure I'm missing something very obvious. Thanks in advance!
EDIT WITH POSSIBLE SOLUTION:
I came up with the code below after some trial and error. It seems to be working well on iPhone and iPad. Any reasons why using this may be a bad idea?
-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
NSArray * myDataArray = [NSArray arrayWithObjects:touches, event, nil];
// If not dragging, send event to next responder
if (!self.dragging){
[self performSelector:@selector(forwardTouches:) withObject:myDataArray afterDelay:0.5];
}
else{
NSLog(@"touchesBegan-else");
[super touchesEnded: touches withEvent: event];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
}
-(void)forwardTouches:(NSArray *)array{
NSSet * mySet = [array objectAtIndex:0];
UIEvent * myEvent = [array objectAtIndex:1];
if (!self.dragging){
[self.nextResponder touchesBegan:mySet withEvent: myEvent];
[self setScrollEnabled:NO];
}
}
-(void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event{
// If not dragging, send event to next responder
if (!self.dragging){
[self.nextResponder touchesMoved: touches withEvent:event];
NSLog(@"touchesMoved");
}
else{
NSLog(@"touchesMoved - else");
[super touchesEnded: touches withEvent: event];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
}
-(void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event{
// If not dragging, send event to next responder
if (!self.dragging){
[self.nextResponder touchesEnded: touches withEvent:event];
[self setScrollEnabled:YES];
NSLog(@"touchesEnded");
}
else{
NSLog(@"touchesEnded - else");
[super touchesEnded: touches withEvent: event];
[NSObject cancelPreviousPerformRequestsWithTarget:self];
}
}