UIScrollView and UIDatePicker (or UIPickerView)
I ran into a very simple problem, but a quick Google search didn’t reveal any simple (or even functional) solutions.
Simply put, trying to use a date picker or picker control inside a scroll view leads to problems: trying to scroll the picker ends up scrolling the scroll view itself.
The solution is very simple: set the UIScrollView’s “canCancelContentTouches” property to NO.
Like a lot of Apple’s documentation, this part makes sense once you already know what it means…
If the value of this property is YES and a view in the content has begun tracking a finger touching it, and if the user drags the finger enough to initiate a scroll, the view receives a touchesCancelled:withEvent: message and the scroll view handles the touch as a scroll. If the value of this property is NO, the scroll view does not scroll regardless of finger movement once the content view starts tracking.
(from the docs).
I actually understood it a lot faster by just reading the comments in UIScrollView.h.
(tested in 3.0, haven’t tried 2.2.1 yet)
Hi! I'm a Toronto-based software engineer, product guy, and all around computer person. I like working on products used by millions of people. I've been doing a lot of mobile development lately.

Hi, thanks for your solution, seems so promising, yet, it didn’t actually solve my problem.
I have a UIDatePicker inside a UIScrollView, and whether I set the canCancelContentTouches to YES or NO, I still can’t use the date picker, it always starts the scrollview’s scrolling action.
The only way I can change date is by tapping…
Are you sure you didn’t add any other lines to make your date picker work in the scrollview?
I’m having the same problem Daniel’s having - I’m still unable to use my picker whether I set canCancelContentTouches to YES or NO, and the only way I can change the value is by tapping.
Was there more to your solution?
Has anyone got this working?
I got mine to work by adding only the line of code he mentioned. Seems silly to mention this but: in order to get the picker control to move you must keep you finger on the picker control “a little longer” so the picker control gets the action and not the scrollview. From what I’ve read the scrollview works with a timer and if there is no swipe/flick by the time the timer fires the action is then passed to the underlying control.
Hope this helps.
You also have to set: @property(nonatomic) BOOL delaysContentTouches to no
Thanks Ian, that worked great.
Thanks, solved my problem.
In my case - using the above code simply disabled the scrolling of the scrollView - unfortunately I do need to be able to scroll, except when using the picker. Any ideas?
I created a UIScrollView subclass and overrode the following methods
@interface PickerAwareUIScrollView : UIScrollView {
}
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view;
- (BOOL)touchesShouldCancelInContentView:(UIView *)view;
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
if ([view isKindOfClass:[UIPickerView class]] || [@"UIPickerTable" isEqualToString:[[view class] description]] ) {
//|| [view isKindOfClass:[UIPicker class]]
return YES;
}
return [super touchesShouldBegin:touches withEvent:event inContentView:view];
}
- (BOOL)touchesShouldCancelInContentView:(UIView *)view {
if ([view isKindOfClass:[UIPickerView class]] || [@"UIPickerTable" isEqualToString:[[view class] description]] ) {
return NO;
}
return [super touchesShouldCancelInContentView:view];
}
You have to set both:
[myView setDelaysContentTouches:NO];
[myView setCanCancelContentTouches:NO];
Great. This was helpfull.
thank you Alan. your solution works
I only added
-(BOOL)delaysContentTouches(Uiview *)view {
if ([view isKindOfClass:[UIPickerView class]] || [@"UIPickerTable" isEqualToString:[[view class] description]] ) {
return NO;
}
return [super touchesShouldCancelInContentView:view];
}
and modefied touchesShouldBegin to be like this
- (BOOL)touchesShouldBegin:(NSSet *)touches withEvent:(UIEvent *)event inContentView:(UIView *)view {
if ([view isKindOfClass:[UIPickerView class]] || [@"UIPickerTable" isEqualToString:[[view class] description]] ) {
//|| [view isKindOfClass:[UIPicker class]]
return YES;
}
return [super touchesShouldBegin:touches withEvent:event inContentView:self]; // self instead of view
}