Search code examples
iosobjective-cuitableviewuidatepicker

UIDatePicker doesn't work when included in a UITableViewCell


I have an application where I regularly use a UIDatePicker inside a table view. Therefore, I made custom DatePickerTableViewCell class, which used to work (a couple of years ago, I don't know the exact date). Now that I'm testing everything again on iOS 14, the date picker does not react on my gestures intended to scroll the wheels. Instead, the table view seems to steal the scroll gesture. Even if I don't set the preferred style to 'Wheels', I can't interact with the date picker.

To reproduce it, you need a table view controller with enough cells to make it scrollable (which cells doesn't matter):

@implementation TableViewController

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return 20;
}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
    return indexPath.row == 0 ? 216 : tableView.rowHeight;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    if (indexPath.row > 0)
        return [tableView dequeueReusableCellWithIdentifier:@"Cell" forIndexPath:indexPath];
    return [[DatePickerTableViewCell alloc] initWithFrame:CGRectMake(0, 0, 320, 216)];
}

@end

and of course the DatePickerTableViewCell class itself:

@interface DatePickerTableViewCell () {
    UIDatePicker *datePicker;
}

@end

@implementation DatePickerTableViewCell

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        datePicker = [[UIDatePicker alloc] initWithFrame:CGRectMake((frame.size.width - 320) / 2, 0, 320, 216)];
        datePicker.autoresizingMask = UIViewAutoresizingFlexibleLeftMargin | UIViewAutoresizingFlexibleBottomMargin
            | UIViewAutoresizingFlexibleRightMargin;
        datePicker.datePickerMode = UIDatePickerModeDate;
        if (@available(iOS 13.4, *)) {
            datePicker.preferredDatePickerStyle = UIDatePickerStyleWheels;
        }
        [self addSubview:datePicker];
    }
    return self;
}

@end

The date picker shows, but I'm not able to interact with it:

enter image description here


Solution

  • You're adding the UIDatePicker as a subview of the UITableViewCell subclass rather than as a subview of the UITableViewCellContentView so it's a sibling rather than child of the content view. My guess is the touches are being absorbed by the content view or the content view isn't being instantiated properly since it's never used.

    The structure of your cell as it currently stands:

    DatePickerTableViewCell
    -- DatePicker
    -- UITableViewCellContentView
    

    Switching this line:

    [self addSubview:datePicker];
    

    to this:

    [self.contentView addSubview:datePicker];
    

    within the DatePickerTableViewCell's - (id)initWithFrame:(CGRect)frame should allow the DatePicker to scroll properly and the structure will be:

    DatePickerTableViewCell
    -- UITableViewCellContentView
    ---- DatePicker