Saturday, June 1, 2013

Using EventKit in iOS

What's EventKit?

It is a framework provided by Apple in iOS 4+ for integrating your iOS app with the built in calendar app (iCal). You are able to retrieve events from the calendar, as well as create, update and delete events.

The Simulator

Although there is no calendar application in the iOS simulator, you can still use it for EventKit development using some open source code such as this.

Fetching Events

Retrieving stored events from a users calendar is super simple. The only parameters you need to specify is a date range and the calendar you want to query.

EKEventStore *eventStore = [[EKEventStore alloc] init];

NSDate *startDate = [NSDate date];
NSDate *endDate   = [NSDate distantFuture];

NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate
NSArray *events = [eventStore eventsMatchingPredicate:predicate];

Calendars within the Calendar app

The calendar app is made up of many calendars, e.g. Home calendar, Work calendar, Birthday calendar etc. Every event created must belong to a calendar, however some calendars are read-only.
You can retrieve the following calendar information in iOS 4:

EKEventStore *eventStore = [[EKEventStore alloc] init];

// Get all calendars
NSArray * calendars = [eventStore calendars];

// Get the default calendar
EKCalendar * calendar = [eventStore defaultCalendarForNewEvents];

// Test if calendar is read-­‐only
[calendar allowsContentModifications];

// Get the associated colour of a calendar
[UIColor colorWithCGColor:calendar.CGColor];

Inserting Events

As the following code illustrates, inserting an event to a users calendar is also fairly simple.

EKEventStore *eventStore = [[EKEventStore alloc] init];

EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
event.calendar  = [eventStore defaultCalendarForNewEvents];
event.title     = @"WWDC";
event.location  = @"San Francisco";
event.notes     = @"Apple Developer Conference";
event.startDate = startDate;
event.endDate   = endDate;
event.allDay    = YES;

[eventStore saveEvent:event span:EKSpanThisEvent error:nil];

Inserting Events with EventKitUI

Instead of saving the created event directly into the event store, a better approach is to use EventKitUI which will allow the user visually check/modify an event before it is inserted.

EKEventStore * eventStore = [[EKEventStore alloc] init];

EKEvent * event = [EKEvent eventWithEventStore:eventStore];
event.title     = title;
event.location  = location;
event.startDate = startDate;
event.endDate   = endDate;
event.notes     = notes;

EKEventEditViewController *controller = [[EKEventEditViewController alloc] init];

controller.eventStore       = eventStore;
controller.event            = event;
controller.editViewDelegate = self;

[self presentViewController:controller animated:YES completion:nil];

If you use EventKitUI, remember to always set the editViewDelegate delegate, and implement a delegate method to handle the dismissal of the view controller window.

-(void)eventEditViewController:(EKEventEditViewController *)controller
         didCompleteWithAction:(EKEventEditViewAction)action {
    switch (action) {
       case EKEventEditViewActionCanceled:
           // User tapped "cancel"
       case EKEventEditViewActionSaved:
           // User tapped "save"
       case EKEventEditViewActionDeleted:
           // User tapped "delete"
    [self dismissViewControllerAnimated:YES completion:nil];