tableview 中的 UIDatePicker 有时无法更改

UIDatePicker in tableview can't be changed sometimes

有时我在使用 UIDatePicker 时遇到问题。我构建了一个带有 UITableView 的屏幕,我可以在其中设置一周中每一天的开始时间和结束时间。
但是,现在我有一种奇怪的行为,即选择器有时不允许更改。它呈灰色但未禁用。当我转动选择器时,它会移动,但当我放手时,它会自动 returns 恢复到之前的值。
该行为是可重现的。我改变了一天并关闭了选择器。改天并关闭选择器。然后我向下滚动一点,tableview 轻微地抽动。如果我现在打开最后更改的选择器,我就会出现上述行为。我注意到 iOS 9 到 11 和不同设备上的行为。
为了更好地理解,我创建了一个 screenshot

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"timeProfilSettingsCell";
TimeProfilSettingsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDate *dateValidFrom = nil;
NSDate *dateValidUntil = nil;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];

[dateFormatter setDateFormat:@"HH:mm"];
[dateFormatter setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];

if (cell == nil)
{
    [tableView registerNib:[UINib nibWithNibName:@"TimeProfilSettingsCell" bundle:nil] forCellReuseIdentifier:CellIdentifier];
    cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
}

TimeInterval *timeInterval = [nma_currentTimeInterval objectAtIndex:indexPath.row];

if (timeInterval.ni_validFrom == TIMEPROFIL_VALUE_ALWAYS_VALID_FROM && timeInterval.ni_validUntil == TIMEPROFIL_VALUE_ALWAYS_VALID_UNTIL && timeInterval.ni_timeIntervalWeekdayActive == 1)
{
    [cell.checkBoxImageView setImage:[UIImage imageNamed:@"IconHakenBlau"]];
}
else if (timeInterval.ni_timeIntervalWeekdayActive == 1)
{
    [cell.checkBoxImageView setImage:[UIImage imageNamed:@"Clock_blue"]];
}
else
{
    [cell.checkBoxImageView setImage:[UIImage imageNamed:@"IconOvalBlau"]];
}

cell.separatorView.backgroundColor = [UIColor colorWithRed:227.0/255.0 green:227.0/255.0 blue:227.0/255.0 alpha:1.0];

cell.weekDayLabel.text = [self getWeekDayName:indexPath.row];

[cell.checkBoxButton addTarget:self action:@selector(checkBoxButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.checkBoxButton setTag:indexPath.row];

cell.validityLabel.textColor = [UIColor colorWithRed:123.0/255.0 green:164.0/255.0 blue:219.0/255.0 alpha:1.0];

[cell.validityButton addTarget:self action:@selector(validityButtonAction:) forControlEvents:UIControlEventTouchUpInside];
[cell.validityButton setTag:indexPath.row];

// Handling so that the picker is closed when it is clicked elsewhere
UITapGestureRecognizer *tapGestureRecognize = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(dismissDatePicker:)];
tapGestureRecognize.numberOfTapsRequired = 1;
[self.view addGestureRecognizer:tapGestureRecognize];

BOOL b_open = NO;

if (b_pickerVisible && ni_touchedRow == indexPath.row)
{
    b_open = YES;
    cell.b_validityPickerVisible = YES;
    [cell.validityStartPicker setHidden:NO];
    [cell.validityStartPicker setEnabled:YES];
    [cell.validityEndPicker setHidden:NO];
    [cell.validityEndPicker setEnabled:YES];
    cell.validityFromLabel.hidden = NO;
    [cell.separatorView setFrame:CGRectMake(cell.separatorView.frame.origin.x, 304, cell.separatorView.frame.size.width, cell.separatorView.frame.size.height)];

    [cell.validityStartPicker setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];
    [cell.validityEndPicker setTimeZone:[NSTimeZone timeZoneWithName:@"UTC"]];

    [cell.validityStartPicker addTarget:self action:@selector(updateValidityStartPicker:) forControlEvents:UIControlEventValueChanged];
    [cell.validityEndPicker addTarget:self action:@selector(updateValidityEndPicker:) forControlEvents:UIControlEventValueChanged];

    if (b_pickerJustOpened)
    {
        b_pickerJustOpened = NO;
        if (tableView.contentOffset.y > 0)
        {
            tableView.contentOffset = CGPointMake(0, tableView.contentOffset.y + 102);
        }
    }

    if (b_pickerValueChanged)
    {
        // Picker-value not changed
    }
    else if (timeInterval.ni_validFrom == TIMEPROFIL_VALUE_INVALID && timeInterval.ni_validUntil == TIMEPROFIL_VALUE_INVALID)
    {
        // Default value, if the entry was previously "not"
        [cell.validityStartPicker setDate:[NSDate dateWithTimeIntervalSince1970:0x20 /* 8:00 */ * 900 /* 15 Minuten x 60 Sekunden */] animated:NO];
        [cell.validityEndPicker setDate:[NSDate dateWithTimeIntervalSince1970:0x40 /* 16:00 */ * 900 /* 15 Minuten x 60 Sekunden */] animated:NO];

        b_pickerValueChanged = YES;

        [cell.validityLabel setTextColor:[UIColor redColor]];
    }
    else
    {
        [cell.validityStartPicker setDate:[NSDate dateWithTimeIntervalSince1970:timeInterval.ni_validFrom * 900 /* 15 Minuten x 60 Sekunden */] animated:NO];
        [cell.validityEndPicker setDate:[NSDate dateWithTimeIntervalSince1970:(timeInterval.ni_validUntil + 1 /* +1 aufrunden auf die volle viertel Stunde*/) * 900 /* 15 Minuten x 60 Sekunden */] animated:NO];
    }
}
else
{
    cell.b_validityPickerVisible = NO;
    cell.validityStartPicker.hidden = YES;
    cell.validityEndPicker.hidden = YES;
    cell.validityFromLabel.hidden = YES;
    [cell.validityStartPicker setEnabled:YES];
    [cell.validityEndPicker setEnabled:YES];
    [cell.separatorView setFrame:CGRectMake(cell.separatorView.frame.origin.x, 88, cell.separatorView.frame.size.width, cell.separatorView.frame.size.height)];
}

if (b_pickerValueChanged && ni_touchedRow == indexPath.row)
{
    if ([[dateFormatter stringFromDate:[cell.validityEndPicker date]] isEqualToString:@"00:00"])
    {
        cell.validityLabel.text = [NSString stringWithFormat:@"%@ - 23:59:59 %@ >", [dateFormatter stringFromDate:[cell.validityStartPicker date]], NSLocalizedString(@"oClock", nil)];
    }
    else
    {
        cell.validityLabel.text = [NSString stringWithFormat:@"%@ - %@ %@ >", [dateFormatter stringFromDate:[cell.validityStartPicker date]], [dateFormatter stringFromDate:[cell.validityEndPicker date]], NSLocalizedString(@"oClock", nil)];
    }

    [cell.validityLabel setTextColor:[UIColor redColor]];
}
else if ((timeInterval.ni_validFrom == TIMEPROFIL_VALUE_ALWAYS_VALID_FROM && timeInterval.ni_validUntil == TIMEPROFIL_VALUE_ALWAYS_VALID_UNTIL && timeInterval.ni_timeIntervalWeekdayActive == 1) || (ni_flagTimeIntervalActive == 0 && timeInterval.ni_timeIntervalWeekdayActive == 1))
{
    cell.validityLabel.text = NSLocalizedString(@"Always", nil);
}
else if (timeInterval.ni_validFrom == TIMEPROFIL_VALUE_INVALID || timeInterval.ni_validUntil == TIMEPROFIL_VALUE_INVALID)
{
    cell.validityLabel.text = NSLocalizedString(@"Not", nil);
}
else
{
    timeInterval.ni_timeIntervalWeekdayActive = 1;
    dateValidFrom = [NSDate dateWithTimeIntervalSince1970:timeInterval.ni_validFrom * 900 /* 15 Minuten x 60 Sekunden */];
    dateValidUntil = [NSDate dateWithTimeIntervalSince1970:(timeInterval.ni_validUntil + 1 /* +1 aufrunden auf die volle viertel Stunde*/) * 900 /* 15 Minuten x 60 Sekunden */];
    if (timeInterval.ni_validUntil == TIMEPROFIL_VALUE_ALWAYS_VALID_UNTIL)
    {
        cell.validityLabel.text = [NSString stringWithFormat:@"%@ - 23:59:59 %@", [dateFormatter stringFromDate:dateValidFrom], NSLocalizedString(@"oClock", nil)];
    }
    else
    {
        cell.validityLabel.text = [NSString stringWithFormat:@"%@ - %@ %@", [dateFormatter stringFromDate:dateValidFrom], [dateFormatter stringFromDate:dateValidUntil], NSLocalizedString(@"oClock", nil)];
    }
}

[cell setSelectionStyle:UITableViewCellSelectionStyleNone];

return cell;
}

我已将部分代码提取到一个项目中,并使其可用于 download

我希望有人有想法。

感谢您的帮助

终于找到了解决问题的方法。在代码中设置语言环境后,选择器没有阻塞。

这是我在代码中 setTimeZone: 之后添加的代码。

[cell.validityStartPicker setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale currentLocale] localeIdentifier]]];
[cell.validityEndPicker setLocale:[[NSLocale alloc] initWithLocaleIdentifier:[[NSLocale currentLocale] localeIdentifier]]];