Учебник по UICalendarView

На WWDC ’22 Apple анонсировала новые элементы управления для UIKit. В этом уроке мы погрузимся в один из самых полезных и универсальных компонентов — UICalendarView.

Что такое UICalendarView

Встроенный компонент выбора даты UIDatePicker теперь доступен как отдельный компонент.

Представление календаря используется для отображения пользователям определенных дат вместе с дополнительной информацией и оформлением для этих конкретных дат.

Например, в приложении «Календарь» даты событий отмечены розоватой точкой под датой. Представление календаря также можно использовать для выбора одной или нескольких дат или вообще без дат.

Вы можете предварительно установить даты, отключить выбор определенных дат и многое другое с помощью UICalendarView.

Чем он отличается от UIDatePicker?

UIDatePicker позволяет пользователю выбрать только один момент времени. Этот выбор является единственным и не может использоваться для выбора диапазона или нескольких дат.

Средство выбора даты по-прежнему необходимо использовать, если вы хотите получить от пользователя информацию о конкретном моменте времени, например, о дате, на которую должна быть зарегистрирована транзакция.

Вы используете представление календаря только для отображения и выбора дат. Если вы хотите управлять выбором даты и времени, используйте UIDatePicker.

Соображения

  • Важное различие между UICalendarView и UIDatePicker заключается в том, что UICalendarView представляет даты как NSDateComponents, в отличие от UIDatePicker, который представляет конкретный момент времени с помощью NSDate.
  • Поскольку даты UICalendarView представлены NSDateComponents, мы обязаны четко указать текущий календарь, который мы хотим использовать. Мы не можем предполагать, что, например, по умолчанию будет установлен григорианский календарь. UICalendarView настроит себя на системный календарь по умолчанию в зависимости от текущего установленного календаря пользователя, если календарь не передается явно.

Здесь мы можем увидеть список доступных календарей. Мы должны четко указать, какой календарь мы хотели бы использовать для нашего ввода.

Начиная

Чтобы создать представление календаря, мы создаем экземпляр UICalendarView и устанавливаем его календарь. Затем мы можем добавить его в представление, используя ограничения автоматического макета.

let calendarView = UICalendarView()
calendarView.calendar = Calendar(identifier: .gregorian)
calendarView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(calendarView)
NSLayoutConstraint.activate([
    calendarView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
    calendarView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
    calendarView.centerXAnchor.constraint(equalTo: view.centerXAnchor)
])

Настройка диапазона дат

UICalendarView имеет метод установки видимого диапазона дат.

Этот набор диапазонов также можно анимировать, чтобы отображать изменения в ответ на ввод данных пользователем или условное изменение во время выполнения.

Чтобы установить видимые компоненты даты, используйте этот метод

func setVisibleDateComponents(
    _ dateComponents: DateComponents,
    animated: Bool
)
// calendarView.setVisibileDateComponents(..., animated: true)

Если предоставленные компоненты даты не находятся в том же календаре, что и UICalendarView, компоненты ввода даты будут преобразованы для использования UICalendarView.calendar при назначении. Это может привести к несоответствию дат и может привести к неверным датам, если две календарные системы не имеют одинаковых дат.

Обработка выбора даты

Мы можем установить свойство поведения выбора в нашем представлении календаря, чтобы определить, какой ввод он будет принимать. Мы можем настроить его с одиночным выбором и множественным выбором. В этом примере мы устанавливаем выбор нескольких дат.

let multiDateSelection = UICalendarSelectionMultiDate(delegate: self)

Существует еще один доступный метод выбора под названием UICalendarSelectionSingleDate, который используется только для выбора отдельных дат.

Делегат UICalendarSelectionMultiDate должен соответствовать UICalendarSelectionMultiDateDelegate. Этот делегат имеет 2 обязательных метода и 2 необязательных метода.

Требуемые методы

  • Первый метод — didSelectDate, и сигнатура его функции выглядит так.
func multiDateSelection(_ selection: UICalendarSelectionMultiDate, didSelectDate dateComponents: DateComponents)

Этот метод вызывается после того, как пользователь выбирает дату в представлении календаря.

  • Другой обязательный метод — didDeselectDate, и сигнатура его функции выглядит так.
func multiDateSelection(_ selection: UICalendarSelectionMultiDate, didDeselectDate dateComponents: DateComponents)

Этот метод вызывается после того, как пользователь снимает выделение с одной из выбранных дат в представлении календаря.

Дополнительные методы

  • Первый опционально доступный метод — canSelectDate.
optional func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canSelectDate dateComponents: DateComponents) -> Bool

Этот вызов определяет, можно ли выбрать дату. Даты, которые нельзя выбрать, будут отключены в представлении календаря.

  • Второй необязательный метод делегата — canDeselectDate.
optional func multiDateSelection(_ selection: UICalendarSelectionMultiDate, canDeselectDate dateComponents: DateComponents) -> Bool

Этот вызов определяет, можно ли отменить выбор даты.

Настройка

UICalendarView позволяет нам предоставить украшения для даты, подобные тем, что вы можете увидеть в приложении системного календаря. Этот компонент имеет wantsDateDecorations, для которого по умолчанию установлено значение true.

Однако вы должны реализовать метод делегата для предоставления этих украшений. Это то, что мы рассмотрим в этом подразделе. Установите делегата calendarView на self и настройте свой контроллер представления на UICalendarViewDelegate.

calendarView.delegate = self
extension ViewController: UICalendarViewDelegate {}

Это соответствие требует от нас реализации одного обязательного метода.

func calendarView(_ calendarView: UICalendarView, decorationFor dateComponents: DateComponents) -> UICalendarView.Decoration?

UICalendarView.Украшение

У украшения есть 3 разных типа. Обычное, изображение и пользовательское представление.

Обычный

Значение по умолчанию init() создает украшение по умолчанию с изображением круга, как показано в приложении системного календаря.

С изображением

Этот инициализатор принимает UIImage, UIColor и UICalendarViewDecorationSize и создает новое украшение на основе изображения с указанным изображением, цветом и размером.

  • image по умолчанию равно circlebadge.fil, если изображение не передается явно.
  • color по умолчанию равно UIColor.systemFillColor, если цвет не передается явно.
  • size по умолчанию равно UICalendarViewDecorationSizeMedium, если размер не указан явно.

С пользовательским видом

Документация Apple объясняет это хорошо.

Создает новое настраиваемое оформление представления, используя предоставленный поставщик представления. Провайдер будет вызываться один раз при первой загрузке декоративного представления. Украшение будет обрезано до границ своего родителя и не может взаимодействовать.

Этот инициализатор принимает UIView и устанавливает его в качестве украшения даты календаря с учетом вышеупомянутых ограничений.

UICalendarView.DecorationSize — это перечисление, представляющее доступные размеры предмета украшения.

UICalendarViewDecorationSizeSmall = 0,
UICalendarViewDecorationSizeMedium = 1,
UICalendarViewDecorationSizeLarge = 2,

Чтобы установить представление оформления, просто укажите требуемое оформление в методе делегата. Например. из сеанса What’s New in UIKit с WWDC ’22:

// Configuring Decorations
func calendarView(
    _ calendarView: UICalendarView,
    decorationFor dateComponents: DateComponents
) -> UICalendarView.Decoration? {
    switch myDatabase.eventType(on: dateComponents) {
    case .none:
        return nil
    case .busy:
        return .default()
    case .travel:
        return .image(airplaneImage, color: .systemOrange)
    case .party:
        return .customView {
            MyPartyEmojiLabel()
        }
    }
}

Вы можете перезагрузить декорации во время выполнения, вызвав метод reloadDecorations(forDateComponents:animated:).

Это принимает массив DateComponents, обозначающий даты, для которых украшение должно быть перезагружено. Вы даже можете анимировать эти изменения.

Заключение

Новый UICalendarView — это мощный компонент для выбора одной или нескольких дат по сравнению с одним моментом времени, как это предусмотрено UIDatePicker. У этих двух компонентов есть свои варианты использования, и их не следует рассматривать как замену ни одному из них.

Используйте UIDatePicker, когда хотите выбрать момент времени. Используйте новый вид календаря, если хотите выбрать одну дату или диапазон дат. Представление календаря принимает DateComponents, а средство выбора даты принимает NSDate.

Спасибо за чтение!

Want to Connect?
If you liked this article, consider buying me a coffee to reward my efforts. You can also choose to sponsor me on Github. With Github sponsors, you can request various services such as pair programming, code reviews, consultancy, and more!