Fetch all events from EventStore EventKit iOS - iphone

i would like to know how to fetch all events from an EventStore using EventKit in iOS.
This way i can specify all events for today:
- (NSArray *)fetchEventsForToday {
NSDate *startDate = [NSDate date];
// endDate is 1 day = 60*60*24 seconds = 86400 seconds from startDate
NSDate *endDate = [NSDate dateWithTimeIntervalSinceNow:86400];
// Create the predicate. Pass it the default calendar.
NSArray *calendarArray = [NSArray arrayWithObject:defaultCalendar];
NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendarArray];
// Fetch all events that match the predicate.
NSArray *events = [self.eventStore eventsMatchingPredicate:predicate];
return events;
}
The correct should use a NSPredicate, which is created with:
NSPredicate *predicate = [self.eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendarArray];
I have tried using
distantPast
distantFuture
as startDate and endDate, no good.
So other A's from other Q's are not exaclty wha im looking for.
Thank you!
EDIT
I have tested and got to the conclusion that i can only fetch events in a period of 4 years maximum. Any way of getting past this? Without using multiple fetches..

Code for fetch all events into array :
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];

This is the method I am using in my app to fetch them.
NSDate *startDate = [NSDate distantPast];
NSDate *endDate = [NSDate distantFuture];

This is code in production
const double secondsInAYear = (60.0*60.0*24.0)*365.0;
NSPredicate* predicate = [eventStore predicateForEventsWithStartDate:[NSDate dateWithTimeIntervalSinceNow:-secondsInAYear] endDate:[NSDate dateWithTimeIntervalSinceNow:secondsInAYear] calendars:nil];
For you, I would recommend looking back and forward ten years.

Related

Get events from all the EKCalendar

I want to get events from all the calendars (home,work,calendar and birthday). I am getting events from the defaultcalendar, but cannot fetch events from Birthday calendar. Any help will be great.
This answer might help you:
NSDate* endDate = [NSDate dateWithTimeIntervalSinceNow:[[NSDate distantFuture] timeIntervalSinceReferenceDate]];
NSArray *calendarArray = [NSArray arrayWithObject:cal];
NSPredicate *fetchCalendarEvents = [eventStore predicateForEventsWithStartDate:[NSDate date] endDate:endDate calendars:calendarArray];
NSArray *eventList = [eventStore eventsMatchingPredicate:fetchCalendarEvents];
for(int i=0; i < eventList.count; i++){
NSLog(#"Event Title:%#", [[eventList objectAtIndex:i] title]);
}

iPhone - How to import native calendar events to my iphone app?

I am doing one simple application using iPhone calendar, where I need to import the iPhone native calendar events into my iPhone app. How can I do this. I have a piece of code but it doesn't seems to be working. I have added some events into my iPhone native calendar. But when i retrieve it's not fetching anything. Here is the piece of code.
-(IBAction)importCalEvents:(id)sender
{
NSArray *caleandarsArray = [[NSArray alloc] init];
caleandarsArray = [[eventStore calendars] retain];
NSLog(#"Calendars from Array : %#", caleandarsArray);
for (EKCalendar *CalendarEK in caleandarsArray)
{
NSLog(#"Calendar Title : %#", CalendarEK.title);
}
}
you can fetch all the calendar events like this.
import these 2 framworks (add if not exists into your project).
1 EventKit/EventKit.h
2) EventKitUI/EventKitUI.h
call this function on button click
-(void)EventList{
EKEventStore *eventStore = [[EKEventStore alloc] init];
NSDate *startDate = [[NSDate alloc] init];
NSDate *endDate = [[NSDate alloc] initWithTimeInterval:3600 sinceDate:startDate];
NSArray *calendars = [eventStore calendars];
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate
endDate:endDate calendars:calendars];
NSArray *matchingEvents = [eventStore eventsMatchingPredicate:predicate];
EKEvent *anEvent;
NSLog(#"Total Events >> %d",[matchingEvents count]);
for (int j=0; j < [ matchingEvents count]; j++) {
anEvent = [matchingEvents objectAtIndex:j];
NSLog(#"Title >>>%#",anEvent.title);
NSLog(#"start date is %# \n End Date is >>> %#",anEvent.startDate,anEvent.endDate);
}
}
And set the startDate and EndDate as per your Requirement.
so you can get all the detatils you want.
Best Luck..

parsing calender events

In my application I am retrieving all calender events using eventkit framework. Now I have parse it in to json to upload it to server. what is the best way to do this, kindly give me an idea if there are any parser libraries or framework which can parse calendar events. Below is the code i used to retrieve events
- (NSMutableArray *)fetchallevents {
NSDate *start = [NSDate distantPast];
NSLog(#"start date is : %#",start);
NSDate *finish = [NSDate distantFuture];
NSLog(#"start date is : %#",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];
}
NSMutableArray *events =[[eventsDict allValues]mutableCopy];
//NSLog(#"the evenets for the day is : %#", events);
return events;
}

how i use iPhone calendar add event?

I want use iPhone calendar add Event.
I try ti.com.calendar module from github but in this module only save startTime EndTime, Title and details.
but, not use allDay repeat or not reminder.
How i use this. in calendar?
I also user notification for reminder. but, after delete event. the notification is not delete.
any suggestion is appreciated
bellow is peace of code. date for alarm is using to match work hours (users don't like to wakeup to do job :)
eventStore = [[EKEventStore alloc] init];
EKEvent *newEvent = [EKEvent eventWithEventStore:eventStore];
newEvent.calendar = eventStore.defaultCalendarForNewEvents;
NSString *titleForEvent = [NSString stringWithFormat:#"In country:%# will be:\n%# event",[mo valueForKey:#"name"],[mo valueForKey:#"necessaryData"]];
newEvent.title = titleForEvent;
newEvent.allDay = YES;
NSDate *date = [mo valueForKey:#"date"];
NSDate *dateAlarm = [mo valueForKey:#"dateAlarm"];
EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:[dateAlarm timeIntervalSinceDate:date]];
if (dateAlarm < [NSDate date]){
dateAlarm = [NSDate dateWithTimeIntervalSinceNow:+18000];
NSDateFormatter *dateForm = [[NSDateFormatter alloc]init];
[dateForm setDateFormat:#"%HH"];
NSString *hourOfAlarm = [dateForm stringFromDate:dateAlarm];
[dateForm release];
NSNumberFormatter *numberForm = [[NSNumberFormatter alloc] init];
NSNumber *hour = [numberForm numberFromString:hourOfAlarm];
[numberForm release];
int difference = 0;
if ([hour intValue] < 9) difference = (9 - [hour intValue]) *3600;
if ([hour intValue] > 17) difference = (17 - [hour intValue]) *3600;
if (difference != 0) {
NSTimeInterval interval = 18000 + difference;
dateAlarm = [NSDate dateWithTimeIntervalSinceNow:interval];
}
alarm = [EKAlarm alarmWithRelativeOffset:[dateAlarm timeIntervalSinceDate:date]];
}
newEvent.startDate = date;
newEvent.endDate = date;
//EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:[dateAlarm timeIntervalSinceDate:date]];
newEvent.alarms = [NSArray arrayWithObject:alarm];
NSError *error;
BOOL saved = [eventStore saveEvent:newEvent span:EKSpanThisEvent error:&error];
if (!saved && error) {
NSLog(#"%#",[error localizedDescription]);
} else [mo setValue:newEvent.eventIdentifier forKey:#"eventIdentifier"];

Diagnosing an autorelease error (EXC_BAD_ACCESS)

I've been playing around with core data and started writing some methods to query different date ranges of data. My core data model is very simple (Entity named Smoke with one field - timestamp (of type date).
When I execute my code, the proper count gets returned, but I get an autorelease error - I used NSZombies to track it to the below method:
- (NSUInteger)retrieveSmokesForUnit:(NSCalendarUnit)unit
{
NSDate *beginDate = [[NSDate alloc] init];
NSDate *endDate = [[NSDate alloc] init];
[self rangeForUnit:unit containingDate:[NSDate date] startsAt:&beginDate andEndsAt:&endDate];
NSInteger count = [self numberOfSmokes:beginDate toDate:endDate];
[beginDate release];
[endDate release];
return count;
}
So I get the concept - I am releasing the NSDate objects beginDate and endDate too many times - but why does that happen? I thought the rule was when you instantiate with alloc, you use release? I don't release them explicitly anywhere else in the code, so there must be something going on behind the scenes. If someone could point me in the right direction, that would be great!
Here are the other methods involved, since the issue must be somewhere in these. I assume it has to do with how I'm passing pointers to the dates around?
The initial call, called in the view controller
- (IBAction)cigButtonPressed
{
NSUInteger smokes = [[DataManager sharedDataManager] retrieveSmokesForUnit:NSWeekCalendarUnit];
NSLog(#"Count test = %i", smokes);
}
This calles the method posted a the beginning of the question, which in turn calls:
- (NSUInteger)numberOfSmokes:(NSDate *)beginDate toDate:(NSDate *)endDate {
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Smoke" inManagedObjectContext:self.managedObjectContext];
NSFetchRequest *request = [[NSFetchRequest alloc] init];
//Create predicate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"(timeStamp >= %#) AND (timeStamp < %#)", beginDate, endDate];
//Setup request
[request setEntity:entity];
[request setPredicate:predicate];
NSError *error;
NSUInteger smokes = [self.managedObjectContext countForFetchRequest:request error:&error];
NSLog(#"Number of smokes retrieved: %d", smokes);
[request release];
return smokes;
}
Thanks!
Edit - left out a related method:
- (void)rangeForUnit:(NSCalendarUnit)unit containingDate:(NSDate *)currentDate startsAt:(NSDate **)startDate andEndsAt:(NSDate **)endDate {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar rangeOfUnit:unit startDate:&*startDate interval:0 forDate:currentDate];
*endDate = [calendar dateByAddingComponents:[self offsetComponentOfUnit:unit] toDate:*startDate options:0];
[calendar release];
}
In:
- (void)rangeForUnit:(NSCalendarUnit)unit containingDate:(NSDate *)currentDate startsAt:(NSDate **)startDate andEndsAt:(NSDate **)endDate {
NSCalendar *calendar = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
[calendar rangeOfUnit:unit startDate:&*startDate interval:0 forDate:currentDate];
*endDate = [calendar dateByAddingComponents:[self offsetComponentOfUnit:unit] toDate:*startDate options:0];
[calendar release];
}
startDate and endDate are output parameters. They are not owned by the caller, hence they should not be released.
Then, in:
- (NSUInteger)retrieveSmokesForUnit:(NSCalendarUnit)unit
{
NSDate *beginDate = [[NSDate alloc] init];
NSDate *endDate = [[NSDate alloc] init];
[self rangeForUnit:unit containingDate:[NSDate date] startsAt:&beginDate andEndsAt:&endDate];
NSInteger count = [self numberOfSmokes:beginDate toDate:endDate];
[beginDate release];
[endDate release];
return count;
}
the following happens:
You create a new NSDate object via +alloc, hence you own it. beginDate points to this new object;
You create a new NSDate object via +alloc, hence you own it. endDate points to this new object;
You send -rangeUnit:containingDate:startsAt:andEndsAt:, passing the address of beginDate and endDate as arguments. Upon return, these two variables point to whatever was placed in them by the method. You do not own the corresponding objects (see above), and you’ve leaked the two NSDate objects you created in steps 1 and 2.
You send -release to both beginDate and endDate. You don’t own them, hence you shouldn’t release them.
In summary:
You shouldn’t be creating new objects for beginDate and endDate since they’re being returned by -rangeUnit… This causes memory leaks;
You shouldn’t be releasing beginDate and endDate because you do not own the objects returned by -rangeUnit… This causes overreleases.
The following code should fix your leaks and overreleases:
- (NSUInteger)retrieveSmokesForUnit:(NSCalendarUnit)unit
{
NSDate *beginDate;
NSDate *endDate;
[self rangeForUnit:unit containingDate:[NSDate date] startsAt:&beginDate andEndsAt:&endDate];
NSInteger count = [self numberOfSmokes:beginDate toDate:endDate];
return count;
}