Search code examples
cocoaekeventkit

How do I set an EKEvent to recur variable days prior to a specific date?


Background Info

I have a class that contains an NSDate object that is used as the date of an EKEvent. The EKEvent is added to the Calendar, sometimes with an EKRecurrenceRule set, with a date that is x amount of days prior to the actual date of the event. For example, if dateOfEvent is 02/01/2013 and the user elects to be alerted 2 days prior, the event will be added to the Calendar on 01/30/2013.

Here is how I am getting the prior date:

NSDateComponents *components = [[NSDateComponents alloc] init];
components.day = ([daysPrior integerValue] * -1);
NSDate *alertDate = [[NSCalendar currentCalendar] dateByAddingComponents:components
                                                                  toDate:[myClass dateOfEvent]
                                                                 options:0];

Current Issue

When setting the EKRecurrenceRule to EKRecurrenceFrequencyMonthly it selects the day of the month from alertDate in each month. With the example above that day ends up being the 30th, however February does not have a 30th day and the event never gets added to February. How can I make it actually set the days prior in each month rather than basing it off a specific number?

Failed Attempts

I tried adding negative days to the recurrence rule hoping it would base it off of the event date I set and move backward but instead it added the event to every day on the calendar.

NSMutableArray *daysOfMonth = [[NSMutableArray alloc] init];
int x;
for (x = 0; x > -31; x--) {
    [daysOfMonth addObject:[NSNumber numberWithInt:x]];
}
EKRecurrenceRule *rule = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly
                                                                      interval:1
                                                                 daysOfTheWeek:nil
                                                                daysOfTheMonth:daysOfMonth
                                                               monthsOfTheYear:nil
                                                                weeksOfTheYear:nil
                                                                 daysOfTheYear:nil
                                                                  setPositions:nil
                                                                           end:nil];

Solution

  • I decided to use an EKAlarm and added it to each event.

    EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:60 * 60 * 24 * ([daysPrior integerValue] * -1)];
    [newEvent addAlarm:alarm];
    

    This way I can add the date of the event on the calendar at its actual date and still alert the user x amount of days prior.