I would be interested in knowing how to add a calendar event in the device, but using swift. I know there are some examples made in Objective-C, but at the moment nothing in swift. Many thanks.
- 
                    Swift 2.0 Implementation added : [HERE ON LINK](http://stackoverflow.com/questions/246249/programmatically-add-custom-event-in-the-iphone-calendar/34790334#34790334) – Dashrath Jan 14 '16 at 13:04
7 Answers
Note: If your app is crashing with This app has crashed because it attempted to access privacy-sensitive data without a usage description.  The app's Info.plist must contain an NSCalendarsUsageDescription key with a string value explaining to the user how the app uses this data., you'll need to add NSCalendarsUsageDescription to your info.plist. Can follow the example here.
Swift 5.0 Version
import Foundation
import EventKit
let eventStore : EKEventStore = EKEventStore()
      
// 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
eventStore.requestAccess(to: .event) { (granted, error) in
  
  if (granted) && (error == nil) {
      print("granted \(granted)")
      print("error \(error)")
      
      let event:EKEvent = EKEvent(eventStore: eventStore)
      
      event.title = "Test Title"
      event.startDate = Date()
      event.endDate = Date()
      event.notes = "This is a note"
      event.calendar = eventStore.defaultCalendarForNewEvents
      do {
          try eventStore.save(event, span: .thisEvent)
      } catch let error as NSError {
          print("failed to save event with error : \(error)")
      }
      print("Saved Event")
  }
  else{
  
      print("failed to save event with error : \(error) or access not granted")
  }
}   
Reference : https://gist.github.com/mchirico/d072c4e38bda61040f91
- 
                    21for who doesn't know you must import : import EventKit to make it work – Mostafa Sultan Sep 22 '15 at 15:08
- 
                    1it gives error "use of unresolved identifier EKEntityTypeEvent". am I missing something ? – Dashrath Jan 14 '16 at 12:26
- 
                    2@Dashrath Use `EKEntityType.Event` (few changes in Swift 2.0) instead – Fares K. A. Feb 12 '16 at 20:49
- 
                    This is not working in iOS 9 devices. Any idea why? I tried the same code, but in ios9 devices, permission is not asking. – Sneha Mar 15 '17 at 04:31
- 
                    1
- 
                    3You need to add "Privacy - Calendars Usage Description" in info.plist – ThetNaing Mizo Aug 04 '17 at 03:35
Swift 3.0 compatible:
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
    let eventStore = EKEventStore()
    eventStore.requestAccess(to: .event, completion: { (granted, error) in
        if (granted) && (error == nil) {
            let event = EKEvent(eventStore: eventStore)
            event.title = title
            event.startDate = startDate
            event.endDate = endDate
            event.notes = description
            event.calendar = eventStore.defaultCalendarForNewEvents
            do {
                try eventStore.save(event, span: .thisEvent)
            } catch let e as NSError {
                completion?(false, e)
                return
            }
            completion?(true, nil)
        } else {
            completion?(false, error as NSError?)
        }
    })
}
And also import EventKit
So you can easily call this method from everywhere:
addEventToCalendar(title: "Girlfriend birthday", description: "Remember or die!", startDate: NSDate(), endDate: NSDate())
If you prefer, you can put this method inside an utiliy class and define it as 'static'.
 
    
    - 167
- 3
- 9
 
    
    - 21,000
- 15
- 120
- 146
- 
                    5You need to add "Privacy - Calendars Usage Description" in info.plist. – ThetNaing Mizo Aug 04 '17 at 03:34
- 
                    2thanks for @ThetNaingMizo for the info.plist info. I will take it a little further and will add the complete entry on the info.plist Key : Privacy - Calendars Usage Description Value : $(PRODUCT_NAME) calendar events – Jiraheta Apr 18 '18 at 16:22
You need to add "Privacy - Calendars Usage Description" to info.plist. Following code works with latest version of xcode and swift 3.
import EventKit
class EventHelper
{
    let appleEventStore = EKEventStore()
    var calendars: [EKCalendar]?
    func generateEvent() {
        let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
        switch (status)
        {
        case EKAuthorizationStatus.notDetermined:
            // This happens on first-run
            requestAccessToCalendar()
        case EKAuthorizationStatus.authorized:
            // User has access
            print("User has access to calendar")
            self.addAppleEvents()
        case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
            // We need to help them give us permission
            noPermission()
        }
    }
    func noPermission()
    {
        print("User has to change settings...goto settings to view access")
    }
    func requestAccessToCalendar() {
        appleEventStore.requestAccess(to: .event, completion: { (granted, error) in
            if (granted) && (error == nil) {
                DispatchQueue.main.async {
                    print("User has access to calendar")
                    self.addAppleEvents()
                }
            } else {
                DispatchQueue.main.async{
                    self.noPermission()
                }
            }
        })
    }
    func addAppleEvents()
    {
        let event:EKEvent = EKEvent(eventStore: appleEventStore)
        event.title = "Test Event"
        event.startDate = NSDate() as Date
        event.endDate = NSDate() as Date
        event.notes = "This is a note"
        event.calendar = appleEventStore.defaultCalendarForNewEvents
        do {
            try appleEventStore.save(event, span: .thisEvent)
            print("events added with dates:")
        } catch let e as NSError {
            print(e.description)
            return
        }   
        print("Saved Event")
    }
}
 
    
    - 1,251
- 16
- 18
I was able to adjust this and eliminate the compiler error mentioned in the comments to the answers above (and a few others), as follows:
 var eventStore : EKEventStore = EKEventStore()
    // 'EKEntityTypeReminder' or 'EKEntityTypeEvent'
    eventStore.requestAccessToEntityType(EKEntityType.Event, completion: {
        (granted, error) in
        if (granted) && (error == nil) {
            print("granted \(granted)")
            print("error \(error)")
            var event:EKEvent = EKEvent(eventStore: eventStore)
            event.title = "Test Title"
            event.startDate = NSDate()
            event.endDate = NSDate()
            event.notes = "This is a note"
            event.calendar = eventStore.defaultCalendarForNewEvents
            eventStore.saveEvent(event, span: EKSpan.ThisEvent, error: nil)
            print("Saved Event")
        } 
    })
However, I still get the following error at the bottom regarding "EKSpan.ThisEvent" : Incorrect argument label in call (have ':span:error:', expected ':span:commit:').
I tried changing "error" to "commit," but it gave me a compiler error saying it expected a Bool instead of nil. It seems like a problem having to do with updates in swift syntax.
Edit: I ended up following this tutorial and was able to get it to work.
- First, ask permission to access the calendar and (if that permission is granted) call a function to add the event. - var savedEventId : String = "" func requestAccessPermission() { let eventStore = EKEventStore() let startDate = NSDate() let endDate = startDate.dateByAddingTimeInterval(60 * 60) // Ends one hour later if (EKEventStore.authorizationStatusForEntityType(.Event) != EKAuthorizationStatus.Authorized) { eventStore.requestAccessToEntityType(.Event, completion: { granted, error in self.createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) }) } else { createEvent(eventStore, title: "Test Title", startDate: startDate, endDate: endDate) } }
- The function that is called in the above code snippet to add the event: - func createEvent(eventStore: EKEventStore, title: String, startDate: NSDate, endDate: NSDate) { let event = EKEvent(eventStore: eventStore) event.title = title event.startDate = startDate event.endDate = endDate event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.saveEvent(event, span: .ThisEvent) savedEventId = event.eventIdentifier } catch { print("Error Saving") } }
 
    
    - 1,348
- 2
- 17
- 42
 
    
    - 595
- 4
- 18
This was really slow on iOS 11.2 Xcode 9.2, so I modified Luca Davanzo's answer to use queues (works a lot faster):
func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
        DispatchQueue.global(qos: .background).async { () -> Void in
            let eventStore = EKEventStore()
            eventStore.requestAccess(to: .event, completion: { (granted, error) in
                if (granted) && (error == nil) {
                    let event = EKEvent(eventStore: eventStore)
                    event.title = title
                    event.startDate = startDate
                    event.endDate = endDate
                    event.notes = description
                    event.calendar = eventStore.defaultCalendarForNewEvents
                    do {
                        try eventStore.save(event, span: .thisEvent)
                    } catch let e as NSError {
                        completion?(false, e)
                        return
                    }
                    completion?(true, nil)
                } else {
                    completion?(false, error as NSError?)
                }
            })
        }
    }
 
    
    - 1,181
- 8
- 5
Async/await without completion handlers:
func addCalendarEvent(eventTitle: String, startDate: Date, endDate: Date) {
    Task {
        do {
            let eventStore = EKEventStore()
            let requestResult: Bool = try await eventStore.requestAccess(to: .event)
            guard requestResult else {
                debugPrint("Couldn't not create a calendar event. Calendar access denied.")
                return
            }
            let event = EKEvent(eventStore: eventStore)
            event.title = eventTitle
            event.startDate = startDate
            event.endDate = endDate
            event.calendar = eventStore.defaultCalendarForNewEvents
            try eventStore.save(event, span: .thisEvent)
        } catch {
            debugPrint("Couldn't not create a calendar event. Error: \(error.localizedDescription)")
            return
        }
    }
}
 
    
    - 21
- 2
same with location and alert
   func addEventToCalendar(title: String, description: String?, startDate: Date, endDate: Date, location: String?, completion: ((_ success: Bool, _ error: NSError?) -> Void)? = nil) {
    DispatchQueue.global(qos: .background).async { () -> Void in
        let eventStore = EKEventStore()
        eventStore.requestAccess(to: .event, completion: { (granted, error) in
            if (granted) && (error == nil) {
                let alarm = EKAlarm(relativeOffset: -3600.0)
                let event = EKEvent(eventStore: eventStore)
                event.title = title
                event.startDate = startDate
                event.endDate = endDate
                event.notes = description
                event.alarms = [alarm]
                event.location = location
                event.calendar = eventStore.defaultCalendarForNewEvents
                do {
                    try eventStore.save(event, span: .thisEvent)
                } catch let e as NSError {
                    completion?(false, e)
                    print ("\(#file) - \(#function) error: \(e.localizedDescription)")
                    return
                }
                completion?(true, nil)
            } else {
                completion?(false, error as NSError?)
                print ("\(#file) - \(#function) error: \(error)")
            }
        })
    }
}
 
    
    - 530
- 6
- 9
 
     
    