Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Check if Event exists on Calendar

I'm having trouble verifying if an event already exists on the user's calendar. I need to check this to determine if I should add it or not, so that I don't create duplicate calendar entries. Right now, I create a duplicate entry every time I run the code.

First, here is how I am creating the calendar entry:

+ (NSString *) addEventToCalenderWithDate : (NSDate *) eventDate
                               eventTitle : (NSString *) eventTitle
                            eventLocation : (NSString *) eventLocation
                              allDayEvent : (BOOL) isAllDay
{
    EKEventStore *store = [[EKEventStore alloc] init];

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

    if (!granted) {

        returnValue = @"calendar error";

    }

    else if ([self eventExists:dateAndTime eventTitle:eventTitle allDayEvent:isAllDay]) {

        returnValue = @"duplicate";

    }

    else {

        EKEvent *event = [EKEvent eventWithEventStore:store];
        event.title = eventTitle;

        event.startDate = dateAndTime;

        if (eventTimeString == (id)[NSNull null] || eventTimeString.length == 0 || isAllDay) {
            event.allDay = YES;
            event.endDate = dateAndTime;
        } else {
            event.endDate = [event.startDate dateByAddingTimeInterval:60*60];  //set 1 hour meeting
        }

        event.location = eventLocation;
        [event setCalendar:[store defaultCalendarForNewEvents]];
        NSError *err = nil;
        [store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

        returnValue = @"success";
    }
}];

return returnValue;


}

This sets the event correctly. However, if I run it again, I expect that the else if clause will return YES and no new entry will be created. However, it always returns NO and I create a new calendar entry with each execution. Here is that method:

+ (BOOL) eventExists : (NSDate *) date
          eventTitle : (NSString *) eventTitle
         allDayEvent : (BOOL) isAllDay
{
    EKEventStore *store = [[EKEventStore alloc] init];

    NSPredicate *predicateForEventOnDate = [[NSPredicate alloc] init];

    if (isAllDay)
        predicateForEventOnDate = [store predicateForEventsWithStartDate:date endDate:date calendars:nil]; // nil will search through all calendars
    else
        predicateForEventOnDate = [store predicateForEventsWithStartDate:date endDate:[date dateByAddingTimeInterval:60*60] calendars:nil]; // nil will search through all calendars

    NSArray *eventOnDate = [store eventsMatchingPredicate:predicateForEventOnDate];
    NSLog(@"eventOnDate: %@", eventOnDate);

    BOOL eventExists = NO;

    for (EKEvent *eventToCheck in eventOnDate) {
        if ([eventToCheck.title isEqualToString:eventTitle]) {
            eventExists = YES;
        }
    }

    return eventExists;
}

As I step through this method, I notice that the NSArray called eventOnDate is nil (the EKEventStore is not nil). I don't know if this means that it simply did not find any matching events or if something else is going on.

What am I doing wrong that won't allow this to identify existing events on the calendar? Thank you!

like image 218
AndroidDev Avatar asked Feb 01 '16 20:02

AndroidDev


1 Answers

The problem appears to be with the date range you have selected for your predicate.

predicateForEventOnDate = [store predicateForEventsWithStartDate:date endDate:date calendars:nil];

This will look for events within a "0" second range because the start and end date of your predicate query is identical.

predicateForEventOnDate = [store predicateForEventsWithStartDate:date endDate:[date dateByAddingTimeInterval:60*60] calendars:nil];

This will only look for events that lie within an hour of the date provided.

NSCalendar *const calendar = NSCalendar.currentCalendar;
NSCalendarUnit const preservedComponents = (NSCalendarUnitYear | NSCalendarUnitMonth | NSCalendarUnitDay);

//strip away hours, minutes and seconds to find date - at start of day
NSDateComponents *startComponents = [calendar components:preservedComponents fromDate:self.date];
//set finished date to 1 full day later
NSDateComponents *offset = [[NSDateComponents alloc] init];
[offset setDay:1];

NSDate *start = [calendar dateFromComponents:startComponents];
NSDate *finish = [calendar dateByAddingComponents:offset toDate:self.date options:0];

NSPredicate *predicateForEventOnDate = [[NSPredicate alloc] init];

if (isAllDay)
    predicateForEventOnDate = [store predicateForEventsWithStartDate:start endDate:finish calendars:nil];

NSArray *eventOnDate = [store eventsMatchingPredicate:predicateForEventOnDate];

This will produce an array that covers events for the full day from start to finish.

like image 150
Cornell Skyers Avatar answered Sep 22 '22 10:09

Cornell Skyers