UIScrollView prevents touchesBegan, touchesMoved, touchesEnded on view controller

morningstar picture morningstar · Sep 16, 2011 · Viewed 19k times · Source

I am handling touches for a couple of my UI components in my view controller (custom subclass of UIViewController). It has methods touchesBegan:withEvent:, touchesMoved:withEvent:, and touchesEnded:withEvent:. It was working fine. Then I added a scroll view (UIScrollView) as the top view in the hierarchy.

Now my touch handlers on the view controller don't work. They don't get called. The interesting thing is, I have various other UI components within the scroll view that do work. Some are buttons, some are custom views that define their own touchesBegan:withEvent:, etc. The only thing that doesn't work is the touch handlers on the view controller.

I thought maybe it's because the scroll view is intercepting those touches for its own purposes, but I subclassed UIScrollView and just to see if I could get it to work I am returning YES always from touchesShouldBegin:withEvent:inContentView: and NO always from touchesShouldCancelInContentView:. Still doesn't work.

If it makes a difference my view controller is within a tab bar controller, but I don't think it's relevant.

Has anyone had this problem and have a ready solution? My guess is the scroll view monkeys up the responder chain. Can I monkey it back? I guess if I can't figure anything else out I'll make the top level view under my scroll view be a custom view and forward the messages on to the view controller, but seems kludgy.

Answer

user1085093 picture user1085093 · Jan 30, 2012

create a subclass of UIScrollView class and override the touchesBegan: and other touch methods as follows:

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

// If not dragging, send event to next responder
  if (!self.dragging){ 
    [self.nextResponder touchesBegan: touches withEvent:event]; 
  }
  else{
    [super touchesBegan: 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]; 
   }
   else{
     [super touchesMoved: 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]; 
   }
   else{
     [super touchesEnded: touches withEvent: event];
   }
}