Creating reminders with complex rules in ios - ios

I want to create a repeating reminder with a complex rule i.e
reminders will have a start date and end date.
reminders will repeat on specific week days only.
On the selected day between start date and end date they will occur on specific time.
- (id)initRecurrenceWithFrequency:(EKRecurrenceFrequency)type interval:(NSInteger)interval daysOfTheWeek:(NSArray *)days daysOfTheMonth:(NSArray *)monthDays monthsOfTheYear:(NSArray *)months weeksOfTheYear:(NSArray *)weeksOfTheYear daysOfTheYear:(NSArray *)daysOfTheYear setPositions:(NSArray *)setPositions end:(EKRecurrenceEnd *)end
appeared to be close but as far as i understand the doc i think i will have to use a combination of events.
I need pointers in direction of creating reminders which happen on specific times of day-> on specific day of week ->within specific start date and end date
Thank you
EDIT
I have tried following things and have faced some problem got some success
EKEvent *event = [EKEvent eventWithEventStore:kEVENTSTORE_SINGLTON];
event.title = #"Event Title test";
event.notes= #"Hope this one displays";
NSArray* rulesArray = [event recurrenceRules];
for (EKRecurrenceRule* rule in rulesArray) [event removeRecurrenceRule:rule];
event.startDate = [NSDate date]; //today
event.endDate = [event.startDate dateByAddingTimeInterval:60*60]; //set 1 hour meeting
[event setCalendar:[kEVENTSTORE_SINGLTON defaultCalendarForNewEvents]];
NSDate *date = [NSDate date];
EKAlarm *alarm1 = [EKAlarm alarmWithAbsoluteDate:[date dateByAddingTimeInterval:60]];
// [event addAlarm:alarm1];
EKAlarm *arm=[EKAlarm alarmWithRelativeOffset:60];
EKAlarm *alarm2 = [EKAlarm alarmWithAbsoluteDate:[date dateByAddingTimeInterval:120]];
// [event addAlarm:alarm2];
EKAlarm *alarm3 = [EKAlarm alarmWithAbsoluteDate:[date dateByAddingTimeInterval:180]];
// [event addAlarm:alarm3];
EKAlarm *alarm4 = [EKAlarm alarmWithAbsoluteDate:[date dateByAddingTimeInterval:240]];
//[event addAlarm:alarm4];
EKRecurrenceRule *objRecurrenceRule=[[EKRecurrenceRule alloc]initRecurrenceWithFrequency:EKRecurrenceFrequencyWeekly interval:1 daysOfTheWeek:#[[EKRecurrenceDayOfWeek dayOfWeek:EKFriday]] daysOfTheMonth:nil monthsOfTheYear:nil weeksOfTheYear:nil daysOfTheYear:nil setPositions:nil end:[EKRecurrenceEnd recurrenceEndWithOccurrenceCount:1]];
//[event addRecurrenceRule:objRecurrenceRule];
event.recurrenceRules=#[objRecurrenceRule];
event.alarms=#[arm];//if i add the relative alarm it works if i add absolute alarm it dosnt.
NSError *err = nil;
[kEVENTSTORE_SINGLTON saveEvent:event span:EKSpanFutureEvents commit:YES error:&err];
if(err)
NSLog(#"some error occured");
So i observed that recurrence rule works with relative alarm that makes sence becoz if alarm has to occour every Friday whats the point of giving absolute alarm
but my requirement is i want alarm to ring every friday say 5 PM date can be relative but time has to be fixed how can i achieve this?

Related

iOS - How to create recurring calendar events with exclusion occurrences (date)?

I'm trying to create a recurrent event into calendar through JSON API, but with exclusion occurences (/date) I don't know how to do it. I think i create a recurrent event, then I delete occurences.
update:
For example, the event repeats every weekend. However, I removed some of the weekends from the time line, creating an exception to a recurrence rule.
How can I get these excluded dates through the API?
my code:
1. CreateEvent from api json:
NSDictionary *dicEvent = [self.arrayEvents objectAtIndex:index];
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = [dicEvent objectForKey:#"RecurrenceRule"];
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
event.startDate = [dicEvent objectForKey:#"startDate"];
event.endDate = [dicEvent objectForKey:#"endDate"];
EKSpan span = EKSpanFutureEvents;
[self.eventStore saveEvent:self.savedEvent span:span commit:YES error:&error];
2. then with exclusion occurrences, I think I delete occurences.
EventStore *eventStore = [[EKEventStore alloc] init];
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendars];
NSArray *results = [eventStore eventsMatchingPredicate:predicate];
for (int i = 0; i < results.count; i++) {
EKEvent *event = [results objectAtIndex:i]
if ([event.occurencesIdentifier isEqualToString: eventoccurencesIdentifier]) {
// delete occurencesIdentifier
break;
}
Please help me where I had gone wrong.
Thanks!

EventKit last event of calendar

I'm making an app in which I sync certain events to a calendar on iPhone.
The problem is, I have no way of telling which events were altered/removed/...
So I need to remove all the events between today and the end date of the last event of the calendar before 'syncing' (read inserting) the new events.
As far as I've seen, the only way to do an action on multiple events at once, is by using enumerateEventsMatchingPredicate:usingBlock: and predicateForEventsWithStartDate:endDate:calendars:
But for this I need a specific end date. (and thus, the end date of the last event in my calendar)
I could always save the event identifier of the last event I insert into this calendar, but I would rather not do this:
If the user uninstalls my app and installs it again later, I don't have the last event identifier anymore. (given that (s)he didn't remove the calendar manually of course)
I could just remove the calendar every time I need to sync the calendar, but then I would lose all passed events.
Any ideas or tips are much appreciated!
For your comment on :
I can't seem to find any way to fetch all the events of a calendar.
Actually you can fetch all the events from calendar :
NSDate *start = ...
NSDate *finish = ...
// use Dictionary for remove duplicates produced by events covered more one year segment
NSMutableDictionary *eventsDict = [NSMutableDictionary dictionaryWithCapacity:1024];
NSDate* currentStart = [NSDate dateWithTimeInterval:0 sinceDate:start];
int seconds_in_year = 60*60*24*365;
// enumerate events by one year segment because iOS do not support predicate longer than 4 year !
while ([currentStart compare:finish] == NSOrderedAscending) {
NSDate* currentFinish = [NSDate dateWithTimeInterval:seconds_in_year sinceDate:currentStart];
if ([currentFinish compare:finish] == NSOrderedDescending) {
currentFinish = [NSDate dateWithTimeInterval:0 sinceDate:finish];
}
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:currentStart endDate:currentFinish calendars:nil];
[eventStore enumerateEventsMatchingPredicate:predicate
usingBlock:^(EKEvent *event, BOOL *stop) {
if (event) {
[eventsDict setObject:event forKey:event.eventIdentifier];
}
}];
currentStart = [NSDate dateWithTimeInterval:(seconds_in_year + 1) sinceDate:currentStart];
}
NSArray *events = [eventsDict allValues];

Detect next UILocalNotification that will fire

Is there a way to find the NSDate for the next local notification that will fire?
For example, I've set up three local notifications:
Notification #1: Set to fire yesterday at 3:00 PM with repeat interval of daily.
Notification #2: Set to fire today at 5:00 PM with repeat interval of daily.
Notification #3: Set to fire tomorrow at 6:00 PM with repeat interval of daily.
Given that is is currently 4:00 PM, the next local notification that will fire is notification #2.
How can I retrieve this local notification and get its date?
I know that I can retrieve these local notifications in an array, but how do I get the next one that will fire based on today's date?
The main goal for your task is to determine the "next fire date" after a given
date for each notification.
The NSLog() output of a UILocalNotification shows this next fire date,
but unfortunately it seems not to be available as a (public) property.
I have taken the code from https://stackoverflow.com/a/18730449/1187415 (with small
improvements) and rewritten that as a category method for UILocalNotification.
(This is not perfect. It does not cover the case that a time zone has been
assigned to the notification.)
#interface UILocalNotification (MyNextFireDate)
- (NSDate *)myNextFireDateAfterDate:(NSDate *)afterDate;
#end
#implementation UILocalNotification (MyNextFireDate)
- (NSDate *)myNextFireDateAfterDate:(NSDate *)afterDate
{
// Check if fire date is in the future:
if ([self.fireDate compare:afterDate] == NSOrderedDescending)
return self.fireDate;
// The notification can have its own calendar, but the default is the current calendar:
NSCalendar *cal = self.repeatCalendar;
if (cal == nil)
cal = [NSCalendar currentCalendar];
// Number of repeat intervals between fire date and the reference date:
NSDateComponents *difference = [cal components:self.repeatInterval
fromDate:self.fireDate
toDate:afterDate
options:0];
// Add this number of repeat intervals to the initial fire date:
NSDate *nextFireDate = [cal dateByAddingComponents:difference
toDate:self.fireDate
options:0];
// If necessary, add one more:
if ([nextFireDate compare:afterDate] == NSOrderedAscending) {
switch (self.repeatInterval) {
case NSDayCalendarUnit:
difference.day++;
break;
case NSHourCalendarUnit:
difference.hour++;
break;
// ... add cases for other repeat intervals ...
default:
break;
}
nextFireDate = [cal dateByAddingComponents:difference
toDate:self.fireDate
options:0];
}
return nextFireDate;
}
#end
Using that, you can sort an array of local notifications according to the
next fire date:
NSArray *notifications = #[notif1, notif2, notif3];
NSDate *now = [NSDate date];
NSArray *sorted = [notifications sortedArrayUsingComparator:^NSComparisonResult(UILocalNotification *obj1, UILocalNotification *obj2) {
NSDate *next1 = [obj1 myNextFireDateAfterDate:now];
NSDate *next2 = [obj2 myNextFireDateAfterDate:now];
return [next1 compare:next2];
}];
Now sorted[0] will be the next notification that fires.

EKEvent AddAlarm Not Working

[Fixed] (Kind of)
Seems you can't have an alarm at the end of an event. I wanted the event to appear spanning x number of days in the calendar, then an alarm to signal when it's due to end. Seems that's not possible. Can only have alarms before the event begins. Silly apple :(
I can't seem to get alarms to save when adding new events. Here's the code...
I want the alarm to sound at the time the event occurs, I thought maybe the all-day option was messing it up but it doesn't save regardless.
Here's the code...
EKEventStore *store = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = title;
event.startDate = [global main].Entry.WithdrawalDate;
event.endDate = [global main].Entry.WithdrawalDate;
//event.allDay = YES;
event.availability = EKEventAvailabilityFree;
event.location = [global main].Holding.Name;
event.notes = [self compileNotes];
//Tried settings the array and adding to it, neither works
//NSArray *arrAlarm = [NSArray arrayWithObject:[EKAlarm alarmWithAbsoluteDate:[global main].Entry.WithdrawalDate]];
//event.alarms= arrAlarm;
EKAlarm * alarm = [EKAlarm alarmWithAbsoluteDate:[global main].Entry.WithdrawalDate];
[event addAlarm:alarm];
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *err;
saved = [store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];

iOS/Xcode: Cannot find recurrent events with predicateForEventsWithStartDate and startDate and endDate outside my search range

In iOS events are stored by their startDate and endDate and their recurrence rules.
If i want to fetch all events for the next 3 days i only get events with the start date within the next three days.
BUT: i do not get events, which are recurring and their startDate is not within my search range, i suppose the reason is that the iOS Calendar is computing on the fly all days when the event occurs, but does not use this information when searching programmaticaly in the EKEventStore.
So ist there a way to find recurring events within my "search date frame" when their startDate is outside the range and some recurrence rules are applied?
best regards,
Christian
NSDate *date_today = [self dateAtBeginningOfDayForDate:[NSDate date]];
NSDate *endDate = [self dateByAddingDays:3 toDate:date_today];
NSPredicate *searchPredicate = [eventStore predicateForEventsWithStartDate:date_today
endDate:endDate calendars:nil];
NSArray *events = [eventStore eventsMatchingPredicate:searchPredicate];

Resources