Интеграция EventKit (системный календарь) в iOS-приложение
EventKit — фреймворк для чтения и записи событий в системный календарь iOS и macOS. Подключить его технически несложно, но есть несколько мест, где разработчики стабильно теряют время.
Разрешения и типичные ошибки
До iOS 17 EventKit использовал один ключ для запроса доступа к Calendar: NSCalendarsUsageDescription в Info.plist. С iOS 17 Apple разделила доступ на два уровня: write-only (NSCalendarsWriteOnlyAccessUsageDescription) и full access (NSCalendarsFullAccessUsageDescription). Приложение, собранное под iOS 17 SDK без NSCalendarsWriteOnlyAccessUsageDescription, вылетит с исключением при попытке создать событие — даже если старый ключ присутствует.
Запрос доступа через EKEventStore.requestFullAccessToEvents возвращает результат асинхронно. Частая ошибка — вызов EKEventStore.save сразу после requestAccess, не дожидаясь ответа пользователя. Результат: EKErrorCalendarAccessDenied в release-сборке, потому что в симуляторе доступ иногда выдаётся автоматически без диалога.
Как мы реализуем
Работа с EKEventStore — тяжёлый объект, его создают один раз и переиспользуют через синглтон или инжектируемый сервис. Создание нового экземпляра на каждый запрос — утечка памяти и замедление работы.
Для создания события:
let store = EKEventStore()
let event = EKEvent(eventStore: store)
event.title = "Meeting"
event.startDate = startDate
event.endDate = endDate
event.calendar = store.defaultCalendarForNewEvents
event.addAlarm(EKAlarm(relativeOffset: -600)) // -10 минут
do {
try store.save(event, span: .thisEvent)
} catch {
// EKErrorNoCalendar, EKErrorEventNotMutable — обрабатываем отдельно
}
EKSpan.thisEvent vs EKSpan.futureEvents — важный параметр при работе с повторяющимися событиями. Клиент хочет изменить одно конкретное событие из серии — используем thisEvent. Хочет изменить всё от этой даты и далее — futureEvents. Перепутать их нельзя.
Подписка на изменения календаря через EKEventStoreChangedNotification нужна, если приложение отображает список событий: пользователь мог изменить событие напрямую через системный Calendar.app, и нужно обновить UI.
Что входит в работу
- Настройка
Info.plistпод iOS 16 и iOS 17+ - Запрос разрешений с корректной обработкой всех состояний (denied, restricted, fullAccess, writeOnly)
- CRUD-операции с событиями: создание, редактирование, удаление
- Работа с повторяющимися событиями и напоминаниями
- Подписка на изменения хранилища
- Обработка нескольких календарей (iCloud, локальный, Exchange)
Сроки
2–3 дня с учётом тестирования на реальном устройстве под iOS 16 и 17. Стоимость рассчитывается индивидуально.







