eventkit
Create, read, and manage calendar events and reminders using EventKit and EventKitUI. Use when adding events to the user's calendar, creating reminders, setting recurrence rules, requesting calendar or reminders access, presenting event editors, choosing calendars, handling alarms, observing calenda
By dpearson2699 · 2,680 installs
npx skills add dpearson2699/swift-ios-skills --skill eventkit
Source repository · Upstream listing
EventKit
Use EventKit for calendar and reminder authorization, CRUD, recurrence, alarms,
and system editors.
Contents
[Availability]( availability)
[Setup]( setup)
[Authorization]( authorization)
[Creating Events]( creating events)
[Fetching Events]( fetching events)
[Reminders]( reminders)
[Recurrence Rules]( recurrence rules)
[Alarms]( alarms)
[EventKitUI Controllers]( eventkitui controllers)
[Observing Changes]( observing changes)
[Common Mistakes]( common mistakes)
[Review Checklist]( review checklist)
[References]( references)
Availability
iOS 17+: Use granular full/write only request methods; legacy
requestAccess(to:) no longer prompts and throws. The system event editor can
create an event without app calendar access. For iOS 10–16, guard those APIs,
use the legacy request plus NSCalendarsUsageDescription /
NSRemindersUsageDescription ; EventKitUI may also need
NSContactsUsageDescription .
iOS 26+: The typed EKEventStore.EventStoreChanged / .changed message is
available behind a guard. Keep EKEventStoreChanged for earlier systems.
Setup
Info.plist Keys
Add the usage description for the access path selected in
[Authorization]( authorization). Do not request broader access merely to simplify
the setup path.
The authorization free system editor path needs no calendar usage string.
Direct writes need write only or full access; reads need full access. Reminders
have only full access.
Event Store
Create a single EKEventStore instance and reuse it. Do not mix objects from
different event stores.
Authorization
Request the narrowest access that matches the feature. Apply the versioned
request path in [Availability]( availability).
Key Access Level
NSCalendarsFullAccessUsageDescription Read + write events
NSCalendarsWriteOnlyAccessUsageDescription Direct write only event creation
NSRemindersFullAccessUsageDescription Read + write reminders
Full Access to Events
Call try await eventStore.requestFullAccessToEvents() when the app needs to
read, edit, delete, or fetch calendar events.
Write Only Access to Events
Use when your app only creates events (e.g., saving a booking) and does not
need to read existing events.
Call try await eventStore.requestWriteOnlyAccessToEvents() before direct
EventKit writes that do not use EKEventEditViewController .
Write only access can create events but cannot fetch calendars or events,
including app created events. Use full access for later query, verification,
modification, or sync.
Full Access to Reminders
Call try await eventStore.requestFullAccessToReminders() before reading,
creating, editing, or deleting reminders.
Checking Authorization Status
Use EKEventStore.authorizationStatus(for: .event) or .reminder before work.
Handle .notDetermined , .fullAccess , .writeOnly , .restricted , .denied ,
and @unknown default ; only .fullAccess supports event/reminder reads.
Creating Events
Setting a Specific Calendar
Adding Structured Location
Fetching Events
After the full access gate in [Authorization]( authorization), use a date range
predicate to query events. The events(matching:) method returns occurrences of
recurring events expanded within the range. Event predicates are capped to a
four year span, and events(matching:) /
enumerateEvents(matching:using:) are synchronous and return only committed
events.
Fetching a Single Event by Identifier
Reminders
Creating a Reminder
Fetching Reminders
Reminder fetches are asynchronous and return through a completion handler.
Completing a Reminder
Recurrence Rules
Use EKRecurrenceRule to create repeating events or reminders.
Simple Recurrence
Complex Recurrence
Editing Recurring Events
When saving changes to a recurring event, specify the span:
Alarms
Attach alarms to events or reminders to trigger notifications.
For reminder geofences, put an EKStructuredLocation and .enter / .leave
proximity on an EKAlarm , then add it to the reminder. See
[references/eventkit patterns.md](references/eventkit patterns.md) for the full
location based reminder pattern.
EventKitUI Controllers
EKEventEditViewController — Create/Edit Events
Present the system event editor for creating or editing events.
On the authorization free path in [Availability]( availability), the editor runs
out of process with its own calendar access. Do not inspect the dismissed
controller to learn what was saved; refetch only with separate full access.
EKEventViewController — View an Event
EKCalendarChooser — Select Calendars
EKCalendarChooser requires write only or full calendar access. In write only
apps, the chooser behaves as writable calendars only and only allows a single
writable calendar selection.
Observing Changes
Register for EKEventStoreChanged notifications to keep your UI in sync when
events are modified outside your app (e.g., by the Calendar app or a sync).
Always re fetch events after receiving this notification. Previously fetched
EKEvent , EKReminder , and EKCalendar objects may be stale. The notification
is posted on the main actor.
Common Mistakes
DON'T: Use legacy requestAccess(to:) on current systems
Keep it only in the compatibility fallback from [Availability]( availability).
DON'T: Save events to a read only calendar
DON'T: Ignore timezone when creating events
DON'T: Forget to commit batched saves
DON'T: Mix EKObjects from different event stores
Review Checklist
[ ] Correct Info.plist usage description keys added for calendars and/or reminders
[ ] Authorization follows the version split in [Availability]( availability)
[ ] Write only calendar access used only for direct event creation, not event/calendar reads
[ ] Authorization status checked before fetching or saving
[ ] Full access required before any event or reminder fetch
[ ] Single EKEventStore instance reused across the app
[ ] Events saved to a writable calendar ( allowsContentModifications checked)
[ ] Recurring event saves specify correct EKSpan ( .thisEvent vs .futureEvents )
[ ] Batched saves validate writable calendars, stage with commit: false ,
call throwing commit() , and on failure reset() unsaved state, discard
every invalidated EKObject , then refetch or reconstruct before retry
[ ] EKEventStoreChanged notification observed to refresh stale data
[ ] Change observation uses the classic notification or guarded typed message per [Availability]( availability)
[ ] Timezone set explicitly for location specific events
[ ] EKObjects not shared across different event store instances
[ ] EventKitUI delegates dismiss controllers in completion callbacks
References
Extended patterns (SwiftUI wrappers, predicate queries, batch operations): [references/eventkit patterns.md](references/eventkit patterns.md)
[EventKit framework](https://sosumi.ai/documentation/eventkit)
[EKEventStore](https://sosumi.ai/documentation/eventkit/ekeventstore)
[EKEvent](https://sosumi.ai/documentation/eventkit/ekevent)
[EKReminder](https://sosumi.ai/documentation/eventkit/ekreminder)
[EKRecurrenceRule](https://sosumi.ai/documentation/eventkit/ekrecurrencerule)
[EKCalendar](https://sosumi.ai/documentation/eventkit/ekcalendar)
[EventKit UI](https://sosumi.ai/documentation/eventkitui)
[EKEventEditViewController](https://sosumi.ai/documentation/eventkitui/ekeventeditviewcontroller)
[EKCalendarChooser](https://sosumi.ai/documentation/eventkitui/ekcalendarchooser)
[Accessing the event store](https://sosumi.ai/documentation/eventkit/accessing the event store)
[Creating a recurring event](https://sosumi.ai/documentation/eventkit/creating a recurring event)