Last active
March 29, 2023 17:26
-
-
Save Fedenieto90/95de03d6f002a79adf54da7b8e7ae72d to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import UIKit | |
import EventKit | |
import EventKitUI | |
typealias EventsCalendarManagerResponse = (_ result: ResultCustomError<Bool, CustomError>) -> 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)) | |
} | |
} | |
// 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) | |
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) | |
} | |
} | |
} | |
// EKEventEditViewDelegate | |
extension EventsCalendarManager: EKEventEditViewDelegate { | |
func eventEditViewController(_ controller: EKEventEditViewController, didCompleteWith action: EKEventEditViewAction) { | |
controller.dismiss(animated: true, completion: nil) | |
} | |
} |
How to solve this? 👆🏻
Please help me
Try with this below, not sure if it works but give it a try @likil33
// Result.swift
//
//
import Foundation
// See https://github.com/antitypical/Result
enum Result<T, E: Swift.Error> {
case success(T)
case failure(E)
public func dematerialize() throws -> T {
switch self {
case let .success(value):
return value
case let .failure(error):
throw error
}
}
}
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
update for swift 5, for the post https://medium.com/@fede_nieto/manage-calendar-events-with-eventkit-and-eventkitui-with-swift-74e1ecbe2524
// Add this ENUM
// Update Callback Argument to "Result" instead of "ResultCustomError"
typealias EventsCalendarManagerResponse = (_ result: Result<Bool, CustomError >) -> Void
// Replace all "Event" Type to "EKEvent" Type
Example:
Instead of
private func generateEvent(event: Event) -> EKEvent {
write
private func generateEvent(event: EKEvent) -> EKEvent {
// Update the following code
instead of