I'm making a MacOS app that will do some analysis on the user's calendar data. For now it only supports Apple's native calendar (EventKit
), but I will later add support to Google, outlook, etc.
Models/Events/Base.swift
:
import Foundation
struct EventData {
var title: String;
var startDate: Date;
var endDate: Date;
var organizerName: String;
var notes: String;
var location: String;
}
struct CalendarData {
var title: String;
var isSubscribed: Bool;
}
class Events {
init() {
checkForAuthorization();
}
func checkForAuthorization() {}
func requestAccess() {}
func getCalendars() -> [CalendarData] {
return [];
}
func getEvents(calendarName: String, from: Date, to: Date) -> [EventData] {
return [];
}
}
Models/Events/iCal.swift
:
import Foundation
import EventKit
class iCal: Events {
let eventStore = EKEventStore();
var calendars: [EKCalendar]?;
override func checkForAuthorization() {
let status = EKEventStore.authorizationStatus(for: EKEntityType.event);
switch (status) {
case EKAuthorizationStatus.notDetermined:
self.requestAccess();
break;
case EKAuthorizationStatus.authorized:
break;
case EKAuthorizationStatus.restricted, EKAuthorizationStatus.denied:
break;
}
}
override func requestAccess() {
eventStore.requestAccess(to: EKEntityType.event, completion:{ (accessGranted: Bool, error: Error?) in
if accessGranted == true {
print("Granted")
} else {
print("Denied")
}
});
}
override func getCalendars() -> [CalendarData] {
let _cals = self.eventStore.calendars(for: .event);
var cals: [CalendarData] = [];
for cal: EKCalendar in _cals {
cals.append(CalendarData(title: cal.title, isSubscribed: cal.isSubscribed));
}
return cals;
}
override func getEvents(calendarName: String, from: Date, to: Date) -> [EventData] {
let cals = self.eventStore.calendars(for: .event);
var events: [EventData] = [];
if let calIndex: Int = cals.firstIndex(where: { $0.title == calendarName }) {
let selectedCalendar: EKCalendar = cals[calIndex];
let predicate = eventStore.predicateForEvents(withStart: from, end: to, calendars: [selectedCalendar])
let _events = eventStore.events(matching: predicate) as [EKEvent];
for ev: EKEvent in _events {
events.append(
EventData(
title: ev.title,
startDate: ev.startDate,
endDate: ev.endDate,
organizerName: ev.organizer?.name ?? "",
notes: ev.notes ?? "",
location: ev.location ?? ""
)
);
}
}
return events;
}
}
And I use this class like this:
let calendar = iCal();
for cal in calendar.getCalendars() {
print("****** \(cal.title) *******\n");
print(calendar.getEvents(calendarName: cal.title, from: Calendar.current.date(byAdding: .day, value: -2, to: Date())!, to: Calendar.current.date(byAdding: .day, value: 1, to: Date())!))
}
This works, but it feels very wrong... I know the semi-colons are not needed, but I always used it in other languages and the linting will delete them anyway after.
Questions:
- How can I improve this?
- Would it be better to instantiate the class
Events
, by passing the calendar type as an argument (eg. iCal, outlook, etc) - Are those structs ok? As in should they go in another file?
Thank you