Skip to content
Mobile
Skill

/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

From plugin
swift-ios-skills
1.3k86 skills1 MCP

Claude Code

$ npx -y skills add dpearson2699/swift-ios-skills --skill eventkit --agent claude-code

SKILL.md

eventkit.SKILL.md
name: eventkit
description: "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 calendar changes, or working with EKEventStore, EKEvent, EKReminder, EKCalendar, EKRecurrenceRule, EKEventEditViewController, EKCalendarChooser, or EventKitUI views."

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.

import EventKit

let eventStore = EKEventStore()

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

func createEvent(
    title: String,
    startDate: Date,
    endDate: Date,
    calendar: EKCalendar? = nil
) throws {
    let event = EKEvent(eventStore: eventStore)
    event.title = title
    event.startDate = startDate
    event.endDate = endDate
    event.calendar = calendar ?? eventStore.defaultCalendarForNewEvents

    try eventStore.save(event, span: .thisEvent)
}

Setting a Specific Calendar

// List writable calendars
let calendars = eventStore.calendars(for: .event)
    .filter { $0.allowsContentModifications }

// Use the first writable calendar, or the default
let targetCalendar = calendars.first ?? eventStore.defaultCalendarForNewEvents
event.calendar = targetCalendar

Adding Structured Location

import CoreLocation

let location = EKStructuredLocation(title: "Apple Park")
location.geoLocation = CLLocation(latitude: 37.3349, longitude: -122.0090)
event.structuredLocation = 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.

func fetchEvents(from start: Date, to end: Date) -> [EKEvent] {
    let predicate = eventStore.predicateForEvents(
        withStart: start,
        end: end,
        calendars: nil  // nil = all calendars
    )
    return eventStore.events(matching: predicate)
        .sorted { $0.startDate < $1.startDate }
}

Fetching a Single Event by Identifier

if let event = eventStore.event(withIdentifier: savedEventID) {
    print(event.title ?? "No title")
}

Reminders

Creating a Reminder

func createReminder(title: String, dueDate: Date) throws {
    let reminder = EKReminder(eventStore: eventStore)
    reminder.title = title
    reminder.calendar = eventStore.defaultCalendarForNewReminders()

    let dueDateComponents = Calendar.current.dateComponents(
        [.year, .month, .day, .hour, .minute],
        from: dueDate
    )
    reminder.dueDateComponents = dueDateComponents

    try eventStore.save(reminder, commit: true)
}

Fetching Reminders

Reminder fetches are asynchronous

Read more
@dpearson2699
Ships withswift-ios-skills

86 agent skills optimized for iOS 26+ development with Swift 6.3 and modern Apple frameworks.

1.3k86 skills1 MCP
Get the whole plugin

Stars on GitHub

Momentum

stars in total
1.3k
Star history of dpearson2699/swift-ios-skills on GitHub, a chart by star-history.com

Other skills on swift-ios-skills.

alarmkit

alarmkit

Implement AlarmKit alarms and countdown timers for iOS and iPadOS with Lock Screen, Dynamic Island, StandBy, and paired Apple…

app-clips

app-clips

Build iOS App Clips with invocation URLs, App Clip Codes, NFC, QR codes, Safari banners, Maps, Messages, target setup, App Store…

More skills from other plugins.

deep-code-review

deep-code-review

In-depth design-focused code review - understands codebase context before evaluating PR changes, posts structured feedback to…

expo1d53k
@expo@expoInstall Skill
modlens

modlens

Plug-in vision for text-only models. Hard rule: when a file path or URL with an image extension (.png, .jpg, .jpeg, .webp, .gif,…

modlens2w4.6k
@liustack@liustackInstall Skill
appllama-app-design-skill

appllama-app-design-sk…

Build native-feeling, benchmark-quality mobile app screens (Expo / React Native). Use when designing or implementing any mobile…

appllama2mo3.9k
@appllama@appllamaInstall Skill

Questions about eventkit.

Which coding agents can use eventkit?
eventkit installs in Claude Code, Codex, Cursor, Gemini CLI, GitHub Copilot, OpenCode and Windsurf with the skills CLI, using each agent's flag shown on this page. Flowy's auto-invocation, which fires a skill when your prompt matches, runs in Claude Code only.