Events & Reminders on iOS

UIEvent & UICalendar Reminders iOS Objective C by Marcio Valenzuela Santiapps.com
UIEvent & UICalendar Reminders iOS Objective C by Marcio Valenzuela Santiapps.com

 

Many apps take advantage of the Events or Reminders on iOS. This is very useful when wanting to give the user the ability to add an event to the calendar or a reminder.

This is quite simple to do, so let’s take a look.  Create an NSObject Class to manage all our EventKit stuff and add the following:

#import <EventKit/EventKit.h>

@property (strong, readonly) EKEventStore *eventStore;

@property (assign, readonly) BOOL eventAccess;

@property (assign, readonly) BOOL reminderAccess;

So far we are simply importing the EventKit, which by the way you must add as Link Library in Target Settings, Summary.  Then we add a property to access the EventStore and some booleans.

– (id) init {
self = [super init]; if (self) {

_eventStore = [[EKEventStore alloc] init];

[_eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {

if (granted) { _eventAccess = YES;

} else {

NSLog(@”Event access not granted: %@”, error);

} }];

[_eventStore requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error) {

if (granted) { _reminderAccess = YES;

} else {
NSLog(@”Reminder access not granted: %@”,

error); }

}]; }

return self; }

Now we can determine whether we have access to that store or not.  Now create a ViewController which will actually use that class:

#import “EventKitController.h”

EventKitController *_eventKitController;

– (id) initWithCoder:(NSCoder *)aDecoder { self = [super initWithCoder:aDecoder]; if (self) {

_eventKitController = [[EventKitController alloc] init]; }

return self; }

If you run this, your device will ask you if you want this app to access your EventStore.  Now let’s add some events.  To do so you must select a calendar and then create the event in order to save it.  This is how you access calendars:

NSArray * allCalendars = [_eventStore calendarsForEntityType:EKEntityMaskEvent |

EKEntityMaskReminder];
NSMutableArray * writableCalendars = [NSMutableArray array]; for (EKCalendar * calendar in allCalendars) {

if (calendar.allowsContentModifications) { [writableCalendars addObject:calendar];

} }

Ok so let’s create an event:

//First create the event and then save it

EKEvent *event = [EKEvent eventWithEventStore:eventStore]; event.title = @”My Coding Event”;
event.startDate = startDate;
event.endDate = endDate;

event.calendar = eventStore.defaultCalendarForNewEvents;

NSError *err;
BOOL saved = [eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

if (!saved) {
NSLog(@”Error creating the event”);

}

This is pretty simple.  Let’s modify the EventKit NSObject class we created to handle this kind of code:

– (void) addEventWithName:(NSString*) eventName startTime:(NSDate*) startDate endTime:(NSDate*) endDate {

if (!_eventAccess) {
NSLog(@”No event acccess!”); return;

}

//1. Create an Event EKEvent *event = [EKEvent

eventWithEventStore:self.eventStore]; event.title = eventName;

//3. Set the start and end date

event.startDate = startDate; event.endDate = endDate;

//4. Set an alarm (This is optional)

EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:-1800]; [event addAlarm:alarm];

//5. Add a note (This is optional)

event.notes = @”This will be exciting”;
//6. Specify the calendar to store the event

event.calendar=self.eventStore.defaultCalendarForNewEvents;

NSError *err;
BOOL success = [self.eventStore

saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

if (!success) {
NSLog(@”There was an error saving event: %@”, err);

} }

Now declare the class in the EventKit NSObject Class by adding this to its interface:

-(void)addEventWithName:(NSString*)eventName startTime:(NSDate*)startDate endTime:(NSDate*)endDate;

and finally add an event from your viewcontroller class by calling this:

[_eventKitController addEventWithName:self.conference.name startTime:self.conference.startDate endTime:self.conference.endDate];

That’s it for events!  There are other options you can look at such as:

//1

EKRecurrenceRule *recurrenceRule =
[[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly interval:1 end:nil];

//2

event.recurrenceRules = @[recurrenceRule];

EKRecurrenceEnd *end = [EKRecurrenceEnd recurrenceEndWithEndDate:endDate]; //or

EKRecurrenceEnd *end = [EKRecurrenceEnd recurrenceEndWithOccurrenceCount:5];

In which case you could modify the EventKit NSObject class to have this method:

– (void) addRecurringEventWithName:(NSString*) eventName startTime:(NSDate*) startDate endTime:(NSDate*) endDate {

if (!_eventAccess) {
NSLog(@”No event acccess!”); return;

}

//1. Create an Event

EKEvent *event = [EKEvent eventWithEventStore:self.eventStore];

//2. Set the title

event.title = eventName;

//3. Set the start and end date

event.startDate = startDate; event.endDate = endDate;

//4. Set an alarm (This is optional)

EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:-1800];

[event addAlarm:alarm];
//5. Add a note (This is optional)

event.notes = @”This will be exciting”;

//6. Add the recurrrence rule.

EKRecurrenceRule *rule = [[EKRecurrenceRule alloc]

initRecurrenceWithFrequency: EKRecurrenceFrequencyYearly interval:1 end:nil];

event.recurrenceRules = @[rule];

//7. Specify the calendar to store the event to

event.calendar = self.eventStore.defaultCalendarForNewEvents;

NSError *err;
BOOL success = [self.eventStore

saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

if (!success) {
NSLog(@”There was an error saving event: %@”, err);

} }

So you would have to declare:

-(void)addRecurringEventWithName:(NSString*)eventName startTime:(NSDate*)startDate endTime:(NSDate*)endDate;

and call it like so:

[_eventKitController addRecurringEventWithName:self.conference.name startTime:self.conference.startDate endTime:self.conference.endDate];

Finally you could delete events by adding a queue to your NSObject class:

dispatch_queue_t _fetchQueue;

and define it in viewDidLoad:

_fetchQueue = dispatch_queue_create(“com.conferencePlannerForGeeks.fetchQueue”, DISPATCH_QUEUE_SERIAL);

and add the delete method like so:

– (void) deleteEventWithName:(NSString*) eventName startTime:(NSDate*) startDate endTime:(NSDate*) endDate {

if (!_eventAccess) {
NSLog(@”No event acccess!”); return;

}
dispatch_async(_fetchQueue, ^{

//1. Create a prediate to find the EKEvent to delete

NSPredicate *predicate = [self.eventStore

predicateForEventsWithStartDate:startDate endDate:endDate
calendars: @[self.eventStore.defaultCalendarForNewEvents]];

NSArray *events =
[self.eventStore eventsMatchingPredicate:predicate];

//2. Post filter the events array

NSPredicate *titlePredicate = [NSPredicate

predicateWithFormat:@”title matches %@”,

eventName]; events = [events

filteredArrayUsingPredicate:titlePredicate];

//3. Delete each of these events

NSError *err;
for (EKEvent *event in events) {

[self.eventStore
removeEvent:event span:event.hasRecurrenceRules ? EKSpanFutureEvents:EKSpanThisEvent commit:NO error:&err];

}

BOOL success = [self.eventStore commit:&err]; if (!success) {

NSLog(@”There was an error deleting event”); }

});
if (!_eventAccess) {

NSLog(@”No event acccess!”);

return; }

}

In the end you would declare it:

-(void)deleteEventWithName:(NSString*)eventName startTime:(NSDate*)startDate endTime:(NSDate*)endDate;

and call it like so:

[_eventKitController deleteEventWithName:self.conference.name startTime:self.conference.startDate endTime:self.conference.endDate];

Reminders are a bit different but still quite simple.  To create a basic reminder you do:

//1

EKReminder *reminder =

[EKReminder reminderWithEventStore:eventStore]; reminder.title = @”Creating my first reminder”; reminder.calendar =

[eventStore defaultCalendarForNewReminders];

//2

NSError *err; BOOL success =

[eventStore saveReminder:reminder commit:YES error:&err];

if (!success) {
NSLog(@”Error creating reminder”);

}

Notice you are still using the EventStore.  So we can still use our EventKit NSObject Class and say:

– (void) addReminderWithTitle:(NSString*) title dueTime:(NSDate*) dueDate {

if (!_reminderAccess) {
NSLog(@”No reminder acccess!”); return;

}

//1.Create a reminder

EKReminder *reminder = [EKReminder

reminderWithEventStore: self.eventStore];

//2. Set the title

reminder.title = title;

//3. Set the calendar

reminder.calendar =
[self calendarForReminders];

//4. Extract the NSDateComponents from the dueDate

NSCalendar *calendar =
[NSCalendar currentCalendar];

NSUInteger unitFlags = NSEraCalendarUnit |

NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit;

NSDateComponents *dueDateComponents = [calendar components:unitFlags fromDate:dueDate];

//5. Set the due date

reminder.dueDateComponents = dueDateComponents;

//6. Save the reminder

NSError *err;
BOOL success = [self.eventStore

saveReminder:reminder commit:YES error:&err];

if (!success) {
NSLog(@”There was an error saving the reminder %@”,

} }

If you want to use a Calendar Title you can define it like so:

#define kRemindersCalendarTitle @”My Coding reminders”

Now you code for that calendar like so:

– (EKCalendar*) calendarForReminders {

//1

for (EKCalendar *calendar in [self.eventStore

calendarsForEntityType:EKEntityTypeReminder]) {

if ([calendar.title isEqualToString:kRemindersCalendarTitle]) {

return calendar; }

}

//2

EKCalendar *remindersCalendar = [EKCalendar

calendarForEntityType:EKEntityTypeReminder eventStore:self.eventStore];

remindersCalendar.title = kRemindersCalendarTitle; remindersCalendar.source =

self.eventStore.defaultCalendarForNewReminders.source;

NSError *err;
BOOL success = [self.eventStore

saveCalendar:remindersCalendar commit:YES error:&err];

if (!success) {
NSLog(@”There was an error creating the reminders

calendar”);

return nil; }

return remindersCalendar; }

Declare the method in the interface:

-(void)addReminderWithTitle:(NSString*)title dueTime:(NSDate*)dueDate;

Now call the method:

[_eventKitController addReminderWithTitle:

[NSString stringWithFormat:@”Buy your %@ ticket”, self.conference.name]

dueTime:[NSDate date]];

Voila, you’ve got calendar interaction for your app!

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s