EventKit integration with the iOS system calendar

App events diverge from the system calendar — duplicates, gaps, reminder failures. We design and implement turnkey iOS calendar integration: from scenario planning to documentation handover. Our engineers eliminate discrepancies and cut manual event editing many times over.

Development and support of all types of mobile applications:

Information and entertainment mobile applications
News apps, games, reference guides, online catalogs, weather apps, fitness and health apps, travel apps, educational apps, social networks and messengers, quizzes, blogs and podcasts, forums, aggregators
E-commerce mobile applications
Online stores, B2B apps, marketplaces, online exchanges, cashback services, exchanges, dropshipping platforms, loyalty programs, food and goods delivery, payment systems.
Business process management mobile applications
CRM systems, ERP systems, project management, sales team tools, financial management, production management, logistics and delivery management, HR management, data monitoring systems
Electronic services mobile applications
Classified ads platforms, online schools, online cinemas, electronic service platforms, cashback platforms, video hosting, thematic portals, online booking and scheduling platforms, online trading platforms

These are just some of the types of mobile applications we work with, and each of them may have its own specific features and functionality, tailored to the specific needs and goals of the client.

Our competencies:

Frequently Asked Questions

Latest works

  • Development of a mobile application for FEEDME
    Development of a mobile application for FEEDME
    971
  • Development of a mobile application for XOOMER
    Development of a mobile application for XOOMER
    868
  • Development of a mobile application for RHL
    Development of a mobile application for RHL
    1288
  • Development of a mobile application for ZIPPY
    Development of a mobile application for ZIPPY
    1143
  • Development of a mobile application for Affhome
    Development of a mobile application for Affhome
    1076
  • Development of a mobile application for the FLAVORS company
    Development of a mobile application for the FLAVORS company
    677

EventKit iOS: why events diverge from the calendar

The divergence begins with the fact that the app and the system calendar read from different sources of truth.

EKEventStore returns a snapshot at the moment of the request, while EKEvent is a reference to a specific record in a specific store (iCloud, local, a subscribed Google calendar).

If time has passed between the read and the write, or the user has switched the primary calendar, the app continues to show a stale state. The user sees a meeting in the app, opens the system calendar — it's not there, and vice versa.

The second source of failure is duplicate events. The app creates an EKEvent without an explicit calendar or with an eventIdentifier that is no longer valid after a reinstall or an account change. Instead of updating the existing record, a second one appears.

This is especially noticeable with recurring events: EKRecurrenceRule expands into a set of exceptions, and with a careless save, part of the series is lost or duplicated.

The third layer is calendar access errors. The NSCalendarsFullAccessUsageDescription permission may be granted but limited to write-only or read-only; when the status changes, the app does not re-read it and continues to operate on a stale assumption.

Separately — EKEventStoreChanged arrives asynchronously, and without proper handling the UI remains with the previous state.

To the user, this looks like "the app is lying": a reminder didn't fire, a meeting got duplicated, a record disappeared after syncing. Let's break down how this is resolved at the level of working with the event store.

What correct calendar integration delivers

Correct calendar handling is first and foremost about data integrity: an event created in the app must not multiply during repeated synchronization.

EventKit iOS provides access to the same stores that the system Calendar app uses, so the key question is not "how to write an event" but "how not to create it a second time." We keep our own event identifier and reconcile it with the system one on every read — duplicates stop appearing even after reinstalling the app or switching devices.

Recurring events are the most common source of discrepancies. The recurrence rule and its exceptions are stored separately from the event itself, and if the app edits only an "instance," the system keeps generating the series according to the original rule.

Our engineers work with the series as a whole: modifying, canceling a single occurrence, and shifting the entire series are three different operations, and each is handled according to its own scenario.

Time zones break the calendar invisibly: an event created in one zone and opened in another may "drift" by several hours or lose its date binding.

We store time with an explicit zone and verify behavior when the zone changes manually — on a device where the system time has been switched, not only in a test environment.

Reminders and access permissions are a separate failure zone. A user may deny calendar access, and the app must not crash but instead correctly explain that synchronization is unavailable.

Once all these scenarios are covered, support requests about "the event disappeared," "it appeared twice," or "it reminded me at the wrong time" drop out of the flow — behavior becomes predictable on any device and in any time zone.

Ways to Access the Calendar: Comparing Approaches

Calendar access in iOS is built on a single framework — EventKit — but there are several ways to work with the data, and they differ in where the record physically resides, who owns it, and what restrictions the system imposes.

The choice of approach determines how the app behaves when there is no network, when permission is revoked, and when there is a conflict of edits between devices.

The key fork in the road is whether you work with the device's local storage or with an account that syncs through the cloud. In the first case, the data never leaves the phone, but it does not survive app reinstallation and is not visible on the user's other devices.

In the second, the record is available anywhere the same account is signed in, but a dependency appears on the state of synchronization and on the provider's own policies.

Approach When it fits Limitations
Local calendar on the device Notes and reminders tied to a specific phone; offline scenarios Does not sync between devices, is lost when the app is deleted, is not visible in the web version
System calendar with a cloud account Events the user expects on all their devices Depends on the state of synchronization, edit conflicts are resolved on the provider's side, some fields are unavailable for writing
A separate app calendar inside the system one You need to isolate the product's events from personal ones, but show them in the stock app The user can hide or delete such a calendar, explicit consent to write is required
Your own server-side storage without EventKit Full control over the event structure and recurrence logic No integration with the stock calendar, the user will not see events where they are used to seeing them

The permissions layer deserves separate mention: the system distinguishes read access from write access, as well as full and limited access, where the user allows only selected calendars to be seen.

The app must correctly handle all states — denial, partial permission, and its revocation in settings at any moment. If this is not accounted for, the interface will show an empty list where there simply are no rights to the data, and the user will perceive this as a failure.

The practical takeaway: for a product's events, a separate calendar inside the system one with cloud synchronization is usually chosen — this gives visibility on all devices and does not mix the data with personal events.

Local storage is left for service records, and a custom server-side layer — only when you need logic that EventKit does not express.

How we implement the integration: stages of work

Work with EventKit starts not with code, but with understanding how the app already interacts with calendars and reminders. If the integration is being built from scratch or rewritten, the order of stages is the same — only the depth of immersion in the first steps changes.

  1. Audit of the current integration. We look at which entity types the app reads and creates, how it handles recurring events, time zones, and synchronization between sources. At this step, calendar conflicts, duplicate entries, and places where the app loses events when switching accounts come to the surface.
  2. Designing the data schema. We determine what is stored locally and what remains the source of truth in the system calendar, how event identifiers are matched during re-synchronization, and what happens when the user deletes a calendar. The schema is fixed before development begins — otherwise migrations will have to be done twice.
  3. Setting up access and permissions. We think through requesting read and write permissions, behavior on partial denial, and feature degradation if the user has closed access. Separately — scenarios where access was granted but later revoked in settings.
  4. Implementation and synchronization. We write the calendar handling layer: creation, update, deletion, processing change notifications. We verify that the app responds correctly to edits made by the user outside of it.
  5. Testing scenarios. We run real cases: multiple calendars on the device, different time zones, recurring events, no network, revoked access. Each scenario is recorded as verifiable — this is the basis for regression in future updates.
  6. Handover of documentation. We provide the data schema description, the access scenario map, deployment instructions, and a verification checklist. The client's team can maintain the integration and develop it without us.

This order reduces the risk that the integration "works in a demo but falls apart on real devices." Describe your task — we'll come back with an estimate and a plan based on these stages.

Artifacts and documentation after implementation

After project delivery, you are left with a set that allows the integration to be developed and maintained without us.

This is not a "folder with source code," but working documentation: diagrams, policies, procedures, and instructions tied to the actual configuration of your application.

  • Integration diagram with the system calendar — how the application gains access to calendars and reminders, which types of events it reads and creates, how it handles recurring events, time zones, and rescheduling. Points where user permissions are required are marked separately.
  • Calendar data access policies — which permissions are requested and at what point, what happens with partial or revoked access, how the application behaves if the user has disabled synchronization. Also included here are the rules for handling the local event cache.
  • Update procedure — the sequence of actions when a new branch of the system is released: what we check on a test device, which scenarios we run before publication, how we roll back if synchronization breaks on some devices.
  • Support instructions — typical calendar-related requests (events don't appear, are duplicated, reminders disappear), what to check first and what data to request from the user. With notes on where support ends and development begins.
  • Integration changelog — what changed and when in the calendar logic, which app version it is associated with, and what it affected. Allows you to quickly understand the cause of a failure after an update.
  • Acceptance checklist — a set of scenarios used to verify correct operation: creating, modifying, deleting an event, recurring series, changing the time zone, revoking and re-granting access.

All of this is handed over in your repository and as separate documents, so that a new engineer on the team can understand the integration without verbal explanations. Describe the task — we will get back to you with an estimate and a work plan.

Case Study: Eliminating Duplicate Events in the Calendar

What It Was

The application is a planner with two-way synchronization via EventKit. The user created an event locally, the application wrote it to the system calendar, and background synchronization pulled changes back.

On a weak connection, the write request was sent again, but the event identifier was saved to the local database only after the system responded. The result: the application did not realize the event had already been created and created it a second time.

The problem accumulated unnoticed. For active users with multiple calendars on their device, by the end of the month 15-20% of records were duplicated, and repeated reminders were perceived as an application malfunction rather than a synchronization error.

What Was Changed

An idempotent key was introduced for each event: before writing, the application checks for the presence of a record in the system calendar using this key and repeats the operation only if it is absent.

The identifier began to be saved to the local database in the same transaction as the event itself — the gap between the write and the system response disappeared.

Merging was also reworked separately: in a version conflict, priority is given to the latest edit by modification time, not by the order in which the response arrived.

The synchronization queue received retries with increasing delay, so a brief network interruption no longer produces a duplicate.

What It Became

Metric Before After
Share of duplicated events 15-20% less than 0.5%
Full synchronization 40-60 seconds 8-12 seconds
Support requests regarding the calendar 30-40 per month isolated

The main gain is not in speed, but in predictability: the user stopped seeing two identical reminders and stopped double-checking the calendar manually. The support load on this topic dropped to isolated requests, and the freed-up time went into product development.

How is EventKit different from direct database access?

EventKit is the system layer for accessing calendars and reminders that Apple provides to apps instead of working directly with the calendar database. Direct access would mean reading and writing storage files directly, bypassing system rules.

That path is closed: an app's sandbox does not allow reaching another container, and attempts to bypass it result in rejection by the app store during review.

EventKit, on the other hand, works as an intermediary: the app requests data, and the system itself decides what and how much to give.

The difference in access rights is fundamental. EventKit grants permissions by entity type — separately for events, separately for reminders — and only after the user's explicit consent.

An app does not see calendars for which access has not been granted, and cannot read their contents even accidentally. With direct access, all of this separation logic would have to be implemented independently, and any error in it would mean a leak of someone else's data. Here, the security model is provided by the system itself.

Performance is also handled on the system side. EventKit returns data through predicates by date range rather than dumping the entire calendar at once.

A request for a specific interval returns only the needed events, and changes arrive through store change notifications — the app does not need to constantly poll the database.

With direct file reading, the entire volume would have to be parsed every time and kept in memory, which on large calendars noticeably hurts responsiveness.

There is also a practical argument: the calendar storage format is an internal system detail that changes from version to version without warning. Code that reads the database directly breaks with every update, and maintenance turns into a chase after changes. EventKit provides a stable programmatic interface: the system updates — the app keeps working.

So the choice here is not between "convenient" and "fast," but between a maintainable solution and one doomed to breakage.

We build calendar integration only through EventKit — this provides correct access rights, predictable load, and operation without modifications when the system updates.

Common technical concerns about integration

Before taking on the task, let's go through the concerns that most often come up in technical discussions. Below are answers on permissions, recurring events, migration, and working with time zones.

What happens if the user has denied access to the calendar?

The app doesn't crash and doesn't block the rest of the functionality — the calendar access request is isolated.

We show a clear explanation of why access is needed and keep a re-request button: the system allows requesting permission again after the status is changed in the settings. If access is read-only, writing is disabled, but event synchronization continues to work.

How are recurring events handled?

A recurring series is not a single event, but a rule plus exceptions. We expand the series into specific occurrences over the required horizon and correctly carry over individual changes: shifting one instance doesn't break the whole series. This eliminates duplicates and "missing" meetings during editing.

Can existing events be transferred without losses?

Yes. Migration proceeds in batches with verification of each event: first we read the source, match by unique identifier, then write to the target calendar.

Conflicts and duplicates are filtered out at the reconciliation stage, and the process can be interrupted and resumed — no data is lost.

What about time zones and daylight saving time?

Events are stored with a reference to the time zone, not to the device's local time. Therefore, a meeting created in one zone is displayed correctly when flying, and the switch to daylight saving time doesn't shift it by an hour. We separately check edge cases — events at the boundary of a time zone change.

How safe is this for user data?

We request the minimum necessary level of access and don't upload calendar contents to our servers without an explicit need. All data operations happen on the device, and transmission, if needed, is protected. Confidentiality is built into the architecture, not added on top.

If your case isn't on the list — describe the task, and we'll come back with an estimate and a plan.

Let's discuss your calendar integration task

To come back with an estimate and an integration plan, we need to understand your task in concrete terms: what the scenario is, what data is being synced and in what volume, and what constraints there are on access and timelines.

From there, the conversation is with an engineer who has built such integrations — not with a sales manager.

Describe the task in your own words — that's enough for us to ask clarifying questions and give realistic timelines. What's useful to specify up front:

  • Scenario: a one-time export of events, ongoing two-way synchronization, or writing reminders from your interface.
  • Data sources: your own server, a third-party service, or local storage on the device.
  • Volume and frequency: how many events, how often they change, whether background operation is needed.
  • Access requirements: which calendars are involved, whether a separate app calendar is needed.
  • Conflict behavior: whose version of an event takes precedence when there's a discrepancy.
  • Platforms and minimum OS versions the app must run on.
  • Constraints: deadlines, phasing, what's already been implemented in-house.

We come back with a work estimate and an integration plan: the stages, what we do at each one, where we need data or access from your side, and when the result will be ready.

If we see a risk during the review — for example, synchronization hitting background task limits — we'll say so before the start, not halfway through.

Let's discuss the task — write to us on whichever channel is convenient, and we'll bring in the engineer responsible for this area.