Подтвердить что ты не робот

Неожиданное поведение UIDatePicker с исламским календарем

Примечание. Ошибка, сообщенная Apple

Номер радара: 29265429 (Ссылка)

Я использую UIDatePicker. Когда я даю григорианский календарь, он отлично работает. Дни начинаются от 1 до 31

Однако, когда я даю Исламский islamicUmmAlQura, это придает мне странное поведение. Дни начинаются от 1 до 30, но есть "2" выше 1 и ниже 30, так что дни выглядят следующим образом 2,1,2,3,4... 30

Я создал новый пустой проект iOS и поместил следующий код в метод viewDidLoad:

let picker = UIDatePicker(frame: CGRect(x: 0, y: 30, width: 0, height: 0))

picker.datePickerMode = .date
picker.date = Date()
picker.calendar = Calendar(identifier: .islamicUmmAlQura)
picker.autoresizingMask = UIViewAutoresizing.flexibleRightMargin
picker.frame.size.width = 300
view.addSubview(picker)

Скриншот:

введите описание изображения здесь

4b9b3361

Ответ 1

Не так сложно сделать свой собственный UIPicker похожим на UIDatePicker, но вы должны быть осторожны, потому что ошибка находится в NSCalendar, а также NSDatePicker.

Просто, чтобы быть понятным, дополнительный "2" не выбирается, так же как 30 не может быть выбран в течение короткого месяца. NSDatePicker не скрывает недействительные дни или месяцы, но делает их невыбираемыми. Таким образом, в григорианском календаре, если вы выберете февраль, вы все равно увидите 29, 30 и 31, но, пытаясь выбрать их, сборщику будет присвоено значение 28. DataPicker определяет, сколько месяцев и дней показывать, вызывая maximumRangeOfUnit: на календарь. В исламском календаре правильный максимум равен {1, 30}, но NSCalendar возвращает {1,31} для maximumRangeOfUnit:NSCalendarUnitDay для всех исламских календарей.

Итак, есть две ошибки. Один из них заключается в том, что NSCalendar говорит, что в исламский месяц может быть 31 день (что я не верю, это правда), а вторая проблема заключается в том, что NSDatePicker показывает 31-й день a 2 вместо 31.

Создание собственного NSDatePicker действительно не так сложно. Количество элементов в каждом компоненте всегда одинаковое (просто убедитесь, что вручную задано 30 для дней и не используйте значение из NSCalendar). Трудная часть решает, является ли дата недействительной и показывает элемент как серый, и не позволяет пикету на нем остановиться. Вы можете использовать rangeOfUnit:InUnit:forDate, чтобы получить количество дней в месяц или количество месяцев в году. Если выбран недопустимый элемент, они перемещают значение вниз до самой высокой допустимой даты (т.е. Если пользователь выбирает 30 в месяц с 29 днями выбора 29).

После выбора строки вы можете конвертировать из дня-месяца в NSDate с помощью dateFromComponents в NSCalendar.