Інтеграція EventKit із системним календарем iOS

Події в застосунку розходяться із системним календарем — дублікати, пропуски, збої нагадувань. Ми проєктуємо та впроваджуємо інтеграцію з календарем iOS під ключ: від опрацювання сценаріїв до передачі документації. Наші інженери усувають розбіжності та скорочують ручне редагування подій у рази.

Розробка та підтримка будь-яких видів мобільних додатків:

Інформаційні та розважальні мобільні програми
Новинки, ігри, довідники, онлайн-каталоги, погодні, фітнес та здоров'я, туристичні, освітні, соціальні мережі та месенджери, квіз, блоги та подкасти, форуми, агрегатори
Мобільні програми електронної комерції
Інтернет-магазини, B2B-додатки, маркетплейси, онлайн-обмінники, кешбек-сервіси, біржі, дропшиппінг-платформи, програми лояльності, доставка їжі та товарів, платіжні системи
Мобільні програми для управління бізнес-процесами
CRM-системи, ERP-системи, управління проектами, інструменти для команди продажів, облік фінансів, управління виробництвом, логістика та доставка, управління персоналом, системи моніторингу даних
Мобільні програми електронних послуг
Дошки оголошень, онлайн-школи, онлайн-кінотеатри, платформи надання електронних послуг, платформи кешбеку, відеохостинги, тематичні портали, платформи онлайн-бронювання та запису, платформи онлайн-торгівлі

Це лише деякі з типів мобільних додатків, з якими ми працюємо, і кожен із них може мати свої специфічні особливості та функціональність, а також бути адаптованим під конкретні потреби та цілі клієнта.

Послуги, які ми пропонуємо
Показано 1 з 1Усі 1734 послуг
Інтеграція EventKit із системним календарем iOS
Простий
~2-3 дні
Часті запитання

EventKit iOS: чому події розходяться з календарем

Розходження починається з того, що застосунок і системний календар читають різні джерела істини. EKEventStore повертає знімок на момент запиту, а EKEvent — це посилання на конкретний запис у конкретному сховищі (iCloud, локальне, підписаний календар Google).

Якщо між читанням і записом минув час або користувач перемкнув основний календар, застосунок продовжує показувати застарілий стан. Користувач бачить зустріч у застосунку, відкриває системний календар — її там немає, і навпаки.

Друге джерело збою — дублікати подій. Застосунок створює EKEvent без явного calendar або з eventIdentifier, який після перевстановлення чи зміни акаунта вже невалідний. Замість оновлення наявного запису з'являється другий.

Особливо помітно на повторюваних подіях: EKRecurrenceRule розгортається в набір винятків, і за неакуратного save частина серії губиться або дублюється.

Третій шар — помилки доступу до календаря. Дозвіл NSCalendarsFullAccessUsageDescription може бути наданий, але обмежений лише записом або лише читанням; при зміні статусу застосунок не перечитує його і продовжує працювати за застарілим припущенням.

Окремо — EKEventStoreChanged надходить асинхронно, і без коректної обробки UI залишається з минулим станом.

Для користувача це виглядає як «застосунок бреше»: нагадування не спрацювало, зустріч задвоїлася, запис зник після синхронізації. Розбираємо, як це закривається на рівні роботи зі сховищем подій.

Що дає коректна інтеграція з календарем

Коректна робота з календарем — це насамперед цілісність даних: подія, створена в застосунку, не повинна розмножуватися під час повторної синхронізації.

EventKit iOS дає доступ до тих самих сховищ, які використовує системний застосунок «Календар», тому ключове питання — не «як записати подію», а «як не створити її вдруге».

Ми тримаємо власний ідентифікатор події та звіряємо його із системним під час кожного читання — дублікати перестають з'являтися навіть після перевстановлення застосунку або зміни пристрою.

Повторювані події — найчастіше джерело розбіжностей. Правило повторення та його винятки зберігаються окремо від самої події, і якщо застосунок виправляє лише «екземпляр», система продовжує генерувати серію за початковим правилом.

Наші інженери працюють із серією загалом: зміна, скасування одного входження та зсув усієї серії — це три різні операції, і кожна обробляється за своїм сценарієм.

Часові пояси ламають календар непомітно: подія, створена в одному поясі та відкрита в іншому, може «з'їхати» на кілька годин або втратити прив'язку до дати.

Ми зберігаємо час із явною зоною та перевіряємо поведінку під час зміни поясу вручну — на пристрої, де системний час переведено, а не лише в тестовому середовищі.

Нагадування та права доступу — окрема зона відмов. Користувач може відхилити доступ до календаря, і застосунок зобов'язаний не падати, а коректно пояснити, що синхронізація недоступна.

Коли всі ці сценарії закриті, звернення до підтримки на тему «подія зникла», «з'явилося двічі» або «нагадало не тоді» зникають із потоку — поведінка стає передбачуваною на будь-якому пристрої та в будь-якому часовому поясі.

Способи доступу до календаря: порівняння підходів

Доступ до календаря в iOS будується на одному фреймворку — EventKit, але варіантів роботи з даними кілька, і вони різняться тим, де фізично лежить запис, хто ним володіє і які обмеження накладає система.

Вибір варіанта визначає, як застосунок поводиться за відсутності мережі, при відкликанні дозволу і при конфлікті правок між пристроями.

Ключове розгалуження — працюєте ви з локальним сховищем пристрою чи з обліковим записом, який синхронізується через хмару. У першому випадку дані не залишають телефон, але не переживають перевстановлення застосунку і не видні на інших пристроях користувача.

У другому запис доступний усюди, де виконано вхід у той самий обліковий запис, однак з'являється залежність від стану синхронізації і від політики самого провайдера.

Варіант Коли підходить Обмеження
Локальний календар на пристрої Нотатки й нагадування, прив'язані до конкретного телефону; сценарії без мережі Не синхронізується між пристроями, втрачається при видаленні застосунку, не видний у веб-версії
Системний календар з хмарним обліковим записом Події, які користувач очікує на всіх своїх пристроях Залежить від стану синхронізації, конфлікти правок вирішуються на боці провайдера, частина полів недоступна для запису
Окремий календар застосунку всередині системного Потрібно ізолювати події продукту від особистих, але показувати їх у штатному застосунку Користувач може приховати або видалити такий календар, потрібна явна згода на запис
Власне сховище на сервері без EventKit Повний контроль над структурою події та логікою повторень Немає інтеграції зі штатним календарем, користувач не побачить події там, де звик

Окремо варто відзначити рівень дозволів: система розрізняє доступ на читання і на запис, а також повний і обмежений доступ, коли користувач дозволяє бачити лише вибрані календарі.

Застосунок зобов'язаний коректно опрацьовувати всі стани — відмову, частковий дозвіл і його відкликання в налаштуваннях у будь-який момент. Якщо цього не врахувати, інтерфейс покаже порожній список там, де даних просто немає прав, і користувач сприйме це як збій.

Практичний висновок: для подій продукту зазвичай беруть окремий календар всередині системного з хмарною синхронізацією — це дає видимість на всіх пристроях і не змішує дані з особистими.

Локальне сховище залишають для службових записів, а власний серверний шар — лише коли потрібна логіка, яку EventKit не виражає.

Як ми впроваджуємо інтеграцію: етапи робіт

Робота з EventKit починається не з коду, а з розуміння того, як застосунок уже взаємодіє з календарями та нагадуваннями. Якщо інтеграція робиться з нуля або переписується, порядок етапів один — змінюється лише глибина занурення на перших кроках.

  1. Аудит поточної інтеграції. Дивимося, які типи сутностей застосунок читає та створює, як обробляє повторювані події, часові пояси та синхронізацію між джерелами. На цьому кроці випливають конфлікти календарів, дубльовані записи та місця, де застосунок втрачає події при перемиканні акаунтів.
  2. Проєктування схеми даних. Визначаємо, що зберігається локально, а що залишається джерелом істини в системному календарі, як зіставляються ідентифікатори подій при повторній синхронізації та що відбувається при видаленні календаря користувачем. Схема фіксується до початку розробки — інакше міграції доведеться робити двічі.
  3. Налаштування доступу та дозволів. Продумуємо запит прав на читання та запис, поведінку при частковій відмові та деградацію функцій, якщо користувач закрив доступ. Окремо — сценарії, коли доступ надано, але згодом відкликано в налаштуваннях.
  4. Реалізація та синхронізація. Пишемо шар роботи з календарями: створення, оновлення, видалення, обробка повідомлень про зміни. Перевіряємо, що застосунок коректно реагує на правки, зроблені користувачем поза ним.
  5. Тестування сценаріїв. Проганяємо реальні кейси: кілька календарів на пристрої, різні часові пояси, повторювані події, відсутність мережі, відкликання доступу. Кожен сценарій фіксується як перевірюваний — це основа регресії при майбутніх оновленнях.
  6. Передача документації. Віддаємо опис схеми даних, карту сценаріїв доступу, інструкції з розгортання та чек-ліст перевірок. Команда замовника може підтримувати інтеграцію та розвивати її без нас.

Такий порядок знижує ризик, що інтеграція «працює на демо, але розсипається на живих пристроях». Опишіть вашу задачу — повернемося з оцінкою та планом за цими етапами.

Артефакти та документація після впровадження

Після здачі проєкту у вас залишається комплект, за яким інтеграцію можна розвивати й супроводжувати без нас. Це не «папка з вихідниками», а робоча документація: схеми, політики, регламенти та інструкції, прив'язані до реальної конфігурації вашого застосунку.

  • Схема інтеграції із системним календарем — як застосунок отримує доступ до календарів і нагадувань, які типи подій читає та створює, як обробляє повторювані події, часові пояси та перенесення. Окремо позначено точки, де потрібні дозволи користувача.
  • Політики доступу до даних календаря — які дозволи запитуються і в який момент, що відбувається при частковому або відкликаному доступі, як застосунок поводиться, якщо користувач заборонив синхронізацію. Тут же — правила роботи з локальним кешем подій.
  • Регламент оновлення — порядок дій при виході нової гілки системи: що перевіряємо на тестовому пристрої, які сценарії проганяємо перед публікацією, як відкочуємося, якщо синхронізація ламається на частині пристроїв.
  • Інструкція для підтримки — типові звернення щодо календаря (події не з'являються, дублюються, зникають нагадування), що дивитися в першу чергу і які дані запитувати в користувача. З позначками, де закінчується підтримка й починається доопрацювання.
  • Журнал змін інтеграції — що і коли змінювалося в логіці роботи з календарем, з якою версією застосунку це пов'язано і на що вплинуло. Дозволяє швидко зрозуміти причину збою після оновлення.
  • Чек-лист приймання — набір сценаріїв, за якими перевіряється коректність роботи: створення, зміна, видалення події, повторювані серії, зміна часового поясу, відкликання та повторна видача доступу.

Усе це передається у вашому репозиторії та у вигляді окремих документів, щоб новий інженер у команді міг розібратися в інтеграції без усних пояснень. Опишіть задачу — повернемося з оцінкою та планом робіт.

Кейс: усунення дублів подій у календарі

Що було

Застосунок — планувальник із двосторонньою синхронізацією через EventKit. Користувач створював подію локально, застосунок записував її в системний календар, а фонова синхронізація підтягувала зміни назад.

На слабкому каналі запит на запис надсилався повторно, а ідентифікатор події зберігався в локальну базу лише після відповіді системи. Результат: застосунок не розумів, що подію вже створено, і заводив її вдруге.

Проблема накопичувалася непомітно. В активних користувачів із кількома календарями на пристрої до кінця місяця набиралося 15-20% подвоєних записів, а повторні нагадування сприймалися як збій застосунку, а не як помилка синхронізації.

Що змінили

Запровадили ідемпотентний ключ на кожну подію: перед записом застосунок перевіряє за ним наявність запису в системному календарі й повторює операцію лише за його відсутності.

Ідентифікатор почали зберігати в локальну базу в тій самій транзакції, що й саму подію, — розрив між записом і відповіддю системи зник.

Окремо переробили злиття: під час конфлікту версій пріоритет надається останній правці за часом зміни, а не за порядком надходження відповіді. Черга синхронізації отримала повторні спроби з наростаючою паузою, тому короткочасний обрив мережі більше не породжує дубль.

Що стало

Метрика До Після
Частка подвоєних подій 15-20% менше 0,5%
Повна синхронізація 40-60 секунд 8-12 секунд
Звернення до підтримки щодо календаря 30-40 на місяць поодинокі

Основний виграш — не у швидкості, а в передбачуваності: користувач перестав бачити два однакових нагадування й перестав перевіряти календар вручну. Навантаження на підтримку з цієї теми впало до поодиноких звернень, а час, що звільнився, пішов на розвиток продукту.

Чим відрізняється EventKit від прямого доступу до бази?

EventKit — це системний шар доступу до календарів і нагадувань, який Apple надає застосункам замість прямої роботи з базою даних календаря. Прямий доступ означав би читання й запис файлів сховища напряму, в обхід системних правил.

Такий шлях закритий: пісочниця застосунку не дає дотягнутися до чужого контейнера, а спроби обійти її призводять до відмови магазину застосунків під час перевірки. EventKit же працює як посередник: застосунок просить дані, система сама вирішує, що і в якому обсязі віддати.

Різниця в правах доступу принципова. EventKit видає дозволи за типами сутностей — окремо на події, окремо на нагадування — і лише після явної згоди користувача. Застосунок не бачить календарі, до яких доступ не надано, і не може прочитати їхній вміст навіть випадково.

За прямого доступу довелося б реалізовувати всю цю логіку розмежування самостійно, а будь-яка помилка в ній означала б витік чужих даних. Тут же модель безпеки забезпечує сама система.

Продуктивність теж вирішується на боці системи. EventKit віддає дані через предикати за діапазоном дат, а не вивантажує весь календар цілком.

Запит на конкретний інтервал повертає лише потрібні події, а зміни надходять через повідомлення про зміну сховища — застосунку не потрібно постійно опитувати базу.

За прямого читання файлу довелося б щоразу розбирати весь обсяг і тримати його в пам'яті, що на великих календарях помітно б'є по чутливості.

Є й практичний аргумент: формат зберігання календаря — внутрішня деталь системи, яка змінюється від версії до версії без попередження. Код, що читає базу напряму, ламається за кожного оновлення, а підтримка перетворюється на гонитву за змінами. EventKit дає стабільний програмний інтерфейс: система оновлюється — застосунок продовжує працювати.

Тому вибір тут не між «зручно» і «швидко», а між підтримуваним і приреченим на поломки рішенням. Ми будуємо інтеграцію з календарем лише через EventKit — це дає коректні права доступу, передбачуване навантаження й роботу без правок під час оновлень системи.

Часті технічні сумніви щодо інтеграції

Перш ніж братися за завдання, розберемо сумніви, які найчастіше виникають у технічних обговореннях. Нижче — відповіді щодо дозволів, повторюваних подій, міграції та роботи з часовими поясами.

Що відбувається, якщо користувач відхилив доступ до календаря?

Застосунок не падає і не блокує решту функціоналу — запит доступу до календаря ізольований. Ми показуємо зрозуміле пояснення, навіщо потрібен доступ, і залишаємо кнопку повторного запиту: система дозволяє запросити дозвіл знову після зміни статусу в налаштуваннях. Якщо доступ лише для читання — запис вимикається, але синхронізація подій продовжує працювати.

Як обробляються повторювані події?

Повторювана серія — це не одна подія, а правило плюс винятки. Ми розгортаємо серію в конкретні входження на потрібному горизонті й коректно переносимо окремі зміни: зсув одного екземпляра не ламає всю серію. Це виключає дублі та «зниклі» зустрічі під час редагування.

Чи можна перенести наявні події без втрат?

Так. Міграція йде пакетами з перевіркою кожної події: спочатку читаємо джерело, зіставляємо за унікальним ідентифікатором, потім пишемо в цільовий календар. Конфлікти та дублі відсікаються на етапі звірки, а процес можна перервати й продовжити — дані не втрачаються.

Що з часовими поясами та переходом на літній час?

Події зберігаються з прив'язкою до часового поясу, а не до локального часу пристрою. Тому зустріч, створена в одному поясі, відображається коректно під час перельоту, а перехід на літній час не зсуває її на годину. Окремо перевіряємо граничні випадки — події на стику зміни поясу.

Наскільки це безпечно для даних користувача?

Ми запитуємо мінімально необхідний рівень доступу й не вивантажуємо вміст календаря на свої сервери без явної необхідності. Усі операції з даними відбуваються на пристрої, а передача, якщо вона потрібна, захищена. Конфіденційність закладена в архітектуру, а не додана зверху.

Якщо ваш випадок не потрапив до списку — опишіть завдання, повернемося з оцінкою та планом.

Обговоримо ваше завдання щодо інтеграції календаря

Щоб повернутися з оцінкою та планом інтеграції, нам потрібно зрозуміти ваше завдання предметно: який сценарій, які дані та в якому обсязі синхронізуються, які обмеження щодо доступів і термінів. Далі розмова ведеться вже з інженером, який робив такі інтеграції, — не з менеджером із продажу.

Опишіть завдання у вільній формі — цього достатньо, щоб ми поставили уточнювальні запитання та назвали реальні терміни. Що корисно вказати одразу:

  • Сценарій: разовий експорт подій, постійна двостороння синхронізація або запис нагадувань із вашого інтерфейсу.
  • Джерела даних: власний сервер, сторонній сервіс або локальне сховище на пристрої.
  • Обсяг і частота: скільки подій, як часто змінюються, чи потрібна робота у фоні.
  • Вимоги до доступів: які календарі задіяні, чи потрібен окремий календар застосунку.
  • Поведінка при конфліктах: чия версія події вважається головною при розбіжності.
  • Платформи та мінімальні версії системи, на яких застосунок має працювати.
  • Обмеження: терміни, етапність, що вже реалізовано власними силами.

Ми повертаємося з оцінкою робіт і планом інтеграції: етапи, що робимо на кожному, де потрібні дані або доступи з вашого боку, коли буде готовий результат.

Якщо під час розбору бачимо ризик — наприклад, синхронізація впреться в ліміти фонових завдань, — скажемо про це до старту, а не в середині.

Обговоримо завдання — напишіть у зручному каналі, і ми підключимо інженера, який відповідає за цей напрям.

Наші компетенції:

Останні роботи

  • Розробка мобільного додатка для компанії FEEDME
    Розробка мобільного додатка для компанії FEEDME
    1010
  • Розробка мобільного додатку для компанії XOOMER
    Розробка мобільного додатку для компанії XOOMER
    903
  • Розробка мобільного додатку для компанії RHL
    Розробка мобільного додатку для компанії RHL
    1332
  • Розробка мобільного додатку для компанії ZIPPY
    Розробка мобільного додатку для компанії ZIPPY
    1180
  • Розробка мобільного додатку для компанії Affhome
    Розробка мобільного додатку для компанії Affhome
    1107
  • Розробка мобільного додатку для компанії FLAVORS
    Розробка мобільного додатку для компанії FLAVORS
    714