Skip to content

Instantly share code, notes, and snippets.

Show Gist options
  • Select an option

  • Save hadanischal/09f2fe57a390b17f06bc3fd6da8a7615 to your computer and use it in GitHub Desktop.

Select an option

Save hadanischal/09f2fe57a390b17f06bc3fd6da8a7615 to your computer and use it in GitHub Desktop.

Revisions

  1. @Fedenieto90 Fedenieto90 revised this gist Feb 20, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions EventsCalendarManager.swift
    Original file line number Diff line number Diff line change
    @@ -150,6 +150,8 @@ class EventsCalendarManager: NSObject {

    }

    // EKEventEditViewDelegate

    extension EventsCalendarManager: EKEventEditViewDelegate {

    func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
  2. @Fedenieto90 Fedenieto90 revised this gist Feb 20, 2019. 1 changed file with 2 additions and 0 deletions.
    2 changes: 2 additions & 0 deletions EventsCalendarManager.swift
    Original file line number Diff line number Diff line change
    @@ -97,6 +97,8 @@ class EventsCalendarManager: NSObject {

    }

    // Check if the event was already added to the calendar

    private func eventAlreadyExists(event eventToAdd: EKEvent) -> Bool {
    let predicate = eventStore.predicateForEvents(withStart: eventToAdd.startDate, end: eventToAdd.endDate, calendars: nil)
    let existingEvents = eventStore.events(matching: predicate)
  3. @Fedenieto90 Fedenieto90 revised this gist Feb 20, 2019. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion EventsCalendarManager.swift
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@ import UIKit
    import EventKit
    import EventKitUI

    typealias EventsCalendarManagerResponse = (_ result: ResultCustomError<Bool, AgendaError>) -> Void
    typealias EventsCalendarManagerResponse = (_ result: ResultCustomError<Bool, CustomError>) -> Void

    class EventsCalendarManager: NSObject {

  4. @Fedenieto90 Fedenieto90 created this gist Feb 20, 2019.
    156 changes: 156 additions & 0 deletions EventsCalendarManager.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,156 @@
    import UIKit
    import EventKit
    import EventKitUI

    typealias EventsCalendarManagerResponse = (_ result: ResultCustomError<Bool, AgendaError>) -> Void

    class EventsCalendarManager: NSObject {

    var eventStore: EKEventStore!

    override init() {
    eventStore = EKEventStore()
    }

    // Request access to the Calendar

    private func requestAccess(completion: @escaping EKEventStoreRequestAccessCompletionHandler) {
    eventStore.requestAccess(to: EKEntityType.event) { (accessGranted, error) in
    completion(accessGranted, error)
    }
    }

    // Get Calendar auth status

    private func getAuthorizationStatus() -> EKAuthorizationStatus {
    return EKEventStore.authorizationStatus(for: EKEntityType.event)
    }

    // Check Calendar permissions auth status
    // Try to add an event to the calendar if authorized

    func addEventToCalendar(event: Event, completion : @escaping EventsCalendarManagerResponse) {
    let authStatus = getAuthorizationStatus()
    switch authStatus {
    case .authorized:
    self.addEvent(event: event, completion: { (result) in
    switch result {
    case .success:
    completion(.success(true))
    case .failure(let error):
    completion(.failure(error))
    }
    })
    case .notDetermined:
    //Auth is not determined
    //We should request access to the calendar
    requestAccess { (accessGranted, error) in
    if accessGranted {
    self.addEvent(event: event, completion: { (result) in
    switch result {
    case .success:
    completion(.success(true))
    case .failure(let error):
    completion(.failure(error))
    }
    })
    } else {
    // Auth denied, we should display a popup
    completion(.failure(.calendarAccessDeniedOrRestricted))
    }
    }
    case .denied, .restricted:
    // Auth denied or restricted, we should display a popup
    completion(.failure(.calendarAccessDeniedOrRestricted))
    }
    }

    // Generate an event which will be then added to the calendar

    private func generateEvent(event: Event) -> EKEvent {
    let newEvent = EKEvent(eventStore: eventStore)
    newEvent.calendar = eventStore.defaultCalendarForNewEvents
    newEvent.title = event.name
    newEvent.startDate = event.dateStart
    newEvent.endDate = event.dateEnd
    // Set default alarm minutes before event
    let alarm = EKAlarm(relativeOffset: TimeInterval(Configuration.addEventToCalendarAlarmMinutesBefore()*60))
    newEvent.addAlarm(alarm)
    return newEvent
    }

    // Try to save an event to the calendar

    private func addEvent(event: Event, completion : @escaping EventsCalendarManagerResponse) {
    let eventToAdd = generateEvent(event: event)
    if !eventAlreadyExists(event: eventToAdd) {
    do {
    try eventStore.save(eventToAdd, span: .thisEvent)
    } catch {
    // Error while trying to create event in calendar
    completion(.failure(.eventNotAddedToCalendar))
    }
    completion(.success(true))
    } else {
    completion(.failure(.eventAlreadyExistsInCalendar))
    }

    }

    private func eventAlreadyExists(event eventToAdd: EKEvent) -> Bool {
    let predicate = eventStore.predicateForEvents(withStart: eventToAdd.startDate, end: eventToAdd.endDate, calendars: nil)
    let existingEvents = eventStore.events(matching: predicate)

    let eventAlreadyExists = existingEvents.contains { (event) -> Bool in
    return eventToAdd.title == event.title && event.startDate == eventToAdd.startDate && event.endDate == eventToAdd.endDate
    }
    return eventAlreadyExists
    }

    // Show event kit ui to add event to calendar

    func presentCalendarModalToAddEvent(event: Event, completion : @escaping EventsCalendarManagerResponse) {
    let authStatus = getAuthorizationStatus()
    switch authStatus {
    case .authorized:
    presentEventCalendarDetailModal(event: event)
    completion(.success(true))
    case .notDetermined:
    //Auth is not determined
    //We should request access to the calendar
    requestAccess { (accessGranted, error) in
    if accessGranted {
    self.presentEventCalendarDetailModal(event: event)
    completion(.success(true))
    } else {
    // Auth denied, we should display a popup
    completion(.failure(.calendarAccessDeniedOrRestricted))
    }
    }
    case .denied, .restricted:
    // Auth denied or restricted, we should display a popup
    completion(.failure(.calendarAccessDeniedOrRestricted))
    }
    }

    // Present edit event calendar modal

    func presentEventCalendarDetailModal(event: Event) {
    let event = generateEvent(event: event)
    let eventModalVC = EKEventEditViewController()
    eventModalVC.event = event
    eventModalVC.eventStore = eventStore
    eventModalVC.editViewDelegate = self
    if let rootVC = UIApplication.shared.keyWindow?.rootViewController {
    rootVC.present(eventModalVC, animated: true, completion: nil)
    }
    }

    }

    extension EventsCalendarManager: EKEventEditViewDelegate {

    func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) {
    controller.dismiss(animated: true, completion: nil)
    }
    }