I would like to insert events in my app, so they can be viewed in iPhone Calendar.app. But since I don't want to mix the user events with those from my app, I wanted to create a EKCalendar like "MyApp Events"
Is this possible ? How would you filter your events otherwise ?
Thanks !
It is absolutely possible to create your own calendar - the catch is that you need iOS 5:
EKEventStore* eventStore = [[EKEventStore alloc] init];
NSString* calendarName = #"My Cal";
EKCalendar* calendar;
// Get the calendar source
EKSource* localSource;
for (EKSource* source in eventStore.sources) {
if (source.sourceType == EKSourceTypeLocal)
{
localSource = source;
break;
}
}
if (!localSource)
return;
calendar = [EKCalendar calendarWithEventStore:eventStore];
calendar.source = localSource;
calendar.title = calendarName;
NSError* error;
bool success= [eventStore saveCalendar:calendar commit:YES error:&error];
if (error != nil)
{
NSLog(error.description);
// TODO: error handling here
}
Do you (or anyone else) have any progress with adding a new Calendar?
I've got the same situation. I can programmatically add events to the default calendar perfectly well, but I'd like to add them to a new calendar, so they don't interfere with the users exsisting events, and can be easily deleted/hidden by the user instead of removing all events manually.
You can't set the properties for a new EKCalendar object. It looks like you can only assign an exsiting one like defaultCalendarForNewEvents to an EKCalendar object.
However, I know it's possible to programmatically create a new calendar, because I've seen iPhone app doing this (without leaving the app).
Could it be that they use a workaround by doing some trick with an external ICS file?
Maybe it is possible to do this by "subscribing" to a local (on the iPhone/app filesystem) generated ICS file, instead of an URL. Does anyone have any experience with this?
This is how you can check out whether a calendar already exists with specific title.
If it does not exists then you can create it programatically.
Declare a Boolean Type Variable
BOOL doesExist=NO;
EKEventStore *eventStore=[[EKEventStore alloc] init];
NSArray *calanders=[eventStore calendarsForEntityType:EKEntityTypeEvent];
//Now Iterate through every calendar in the array and match its title
// with the title that you want to create
for(EKCalendar calendar in calendars)
{
if([[calendar title] isEqualToString:#"youdesiredname"])
{
doesExist=YES;
}
}
// so now check if our bool variable contains value YES it means that a calendar with same name/title already exists.if no then you can create
if(!doesExist)
{
NSString* calendarName = #"DesiredCalendarName";
EKCalendar* calendar;
EKSource* localSource;
for (EKSource* source in eventStore.sources) {
if (source.sourceType == EKSourceTypeLocal)
{
localSource = source;
break;
}
if (!localSource)
return;
calendar = [EKCalendar calendarWithEventStore:eventStore];
calendar.source = localSource;
calendar.title = calendarName;
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
calendar = [eventStore calendarWithIdentifier:self.calendarIdentifier];
event.calendar = calendar;
// Set the start date to the current date/time and the event duration to one hour
NSDate *startDate = [NSDate date];
event.startDate = startDate;
event.endDate = [startDate dateByAddingTimeInterval:3600];
//And to save the event to the event database:
NSError *error = nil;
BOOL result = [eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:&error];
if (result)
{
NSLog(#"Saved event to event store.")
}
else
{
NSLog(#"Error saving event: %#.", saveError);
}
NSError* error;
bool success= [eventStore saveCalendar:calendar commit:YES error:&error];
if (error != nil)
{
NSLog(error.description);
}
}
Related
I am developing a calendar app using eventkit framework in ios 6. I am trying to get the permission using the [self.store respondsToSelector:#selector(requestAccessToEntityType:completion:)] method and after getting permission to access the calendars, I am trying to create the new calendar with identifier using EKSourceTypeLocal source and add events to the newly created calendar. I am facing the problem here that when I try to run the app in iPhone 4s it shows the error that "calendar has no source" and it doesn't save my calendar and hence no events gets added to the calendar. I don't know what am I doing wrong here. Please guide me to solve this issue.
I am posting my code below
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
NSLog(#"in view did load method");
// For iOS 6.0 and later
self.store = [[EKEventStore alloc] init];
if([self.store respondsToSelector:#selector(requestAccessToEntityType:completion:)]) {
[self.store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
// handle access here
dispatch_async(dispatch_get_main_queue(), ^{
if (granted) {
NSLog(#"permission granted");
EKCalendar *myCalendar;
EKSource *myLocalSource = nil;
for (EKSource *calendarSource in self.store.sources) {
if (calendarSource.sourceType == EKSourceTypeLocal) {
myLocalSource = calendarSource;
break;
}
}
if (!myLocalSource)
return;
NSString *mycalIndentifier = [[NSUserDefaults standardUserDefaults] valueForKey:#"my_calendar_identifier"];
if (mycalIndentifier == NULL) {
// Create a new calendar of type Local... save and commit
myCalendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.store];
myCalendar.title = #"New_Calendar";
myCalendar.source = myLocalSource;
NSString *calendarIdentifier = myCalendar.calendarIdentifier;
NSError *error = nil;
[_store saveCalendar:myCalendar commit:YES error:&error];
if (!error) {
NSLog(#"created, saved, and commited my calendar with id %#", myCalendar.calendarIdentifier);
[[NSUserDefaults standardUserDefaults] setObject:calendarIdentifier forKey:#"my_calendar_identifier"];
} else {
NSLog(#"an error occured when creating the calendar = %#", error.description);
error = nil;
}
//create an event
// Create a new event... save and commit
EKEvent *myEvent = [EKEvent eventWithEventStore:_store];
myEvent.allDay = NO;
myEvent.startDate = [NSDate date];
myEvent.endDate = [NSDate date];
myEvent.title = #"Birthday";
myEvent.calendar = myCalendar;
[_store saveEvent:myEvent span:EKSpanThisEvent commit:YES error:&error];
if (!error) {
NSLog(#"the event saved and committed correctly with identifier %#", myEvent.eventIdentifier);
} else {
NSLog(#"there was an error saving and committing the event");
error = nil;
}
EKEvent *savedEvent = [_store eventWithIdentifier:myEvent.eventIdentifier];
NSLog(#"saved event description: %#",savedEvent);
}
else{
myCalendar = [_store calendarWithIdentifier:mycalIndentifier];
}
}
else if(!granted){
NSLog(#"Permission not granted");
}
else{
NSLog(#"error = %#", error.localizedDescription);
}
});
}];
}
}
this is the error I am getting :
Predicate call to calendar daemon failed: Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)"
not saved = Error Domain=EKErrorDomain Code=14 "Calendar has no source" UserInfo=0x1d5f6950 {NSLocalizedDescription=Calendar has no source}
UPDATE :
I solved the problem using this link try it
Problem seems to be that the local calendar is hidden when iCloud is enabled so you need to handle both cases (iCloud enabled and not).
See this answer for a working solution: https://stackoverflow.com/a/15980556/72176
I am trying to make an app that permits the user to make events in one specified calendar.
The problem is that:
I can't find a solution to know if there's a calendar with the title that I want to use.
If the list is empty I write a code that creates the calendar but if the list isn't empty I need to know if there's a calendar with the calendar.title that I need.
If there isn't any calendar, I create the calendar; if there is I add the event to this calendar.
Below is the code I am using:
EKEvent *myEvent;
EKEventStore *store;
EKSource* localSource;
EKCalendar* newCal;
store = [[EKEventStore alloc] init];
myEvent = [EKEvent eventWithEventStore: store];
NSString* title = [arguments objectAtIndex:1];
NSString* location = [arguments objectAtIndex:2];
NSString* message = [arguments objectAtIndex:3];
NSString* startDate = [arguments objectAtIndex:4];
NSString* endDate = [arguments objectAtIndex:5];
NSString* calendarTitle = [arguments objectAtIndex:6];
//NSString* calID = nil;
//int i = 0;
EKCalendar* calendar = nil;
if(calendarTitle == nil){
calendar = store.defaultCalendarForNewEvents;
} else {
NSIndexSet* indexes = [store.calendars indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
*stop = false;
EKCalendar* cal = (EKCalendar*)obj;
if(cal.title == calendarTitle){
*stop = true;
}
return *stop;
}];
if (indexes.count == 0) {
//if list is empty i haven't calendars then i need to create it
for (EKSource* source in store.sources)
{
if (source.sourceType == EKSourceTypeLocal)
{
localSource = source;
break;
}
}
if (!localSource) return;
newCal = [EKCalendar calendarWithEventStore:store];
calendar.source = localSource;
calendar.title = calendarTitle;
NSError* error;
bool success = [store saveCalendar:newCal commit:YES error:&error];
if (error != nil)
{
NSLog(error.description);
}
//calendar created
} else {
//!Empty List i need to search the calendar with the title = calendarTitle
//And if there isn't i need to create it
//calendar = [store.calendars objectAtIndex:[indexes firstIndex]];
}
}
I think the problem is your implementation of indexesOfObjectsPassingTest. You're not returning any indexes, and since you try to stop it after it finds one index, you should just use the singular version indexOfObjectPassingTest. You can very simply write that like this:
NSUInteger* indx = [store.calendars indexOfObjectPassingTest:^BOOL(EkCalendar *cal, NSUInteger idx, BOOL *stop) {
return [cal.title isEqualToString:calendarTitle];
}];
Then, after checking to see that index is not NSNotFound use
calendar = store.calendars[indx];
i have successfully created calendar by coding and create events in that calendar.I am able to delete the calendar by coding but when i select iPhone's calendar and delete newly created calendar this time delete not working.
please suggest.
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKCalendar *calendar = [EKCalendar calendarWithEventStore:eventStore];
calendar.title = CALENDAR_TITLE;
// Iterate over all sources in the event store and look for the local source
EKSource *theSource = nil;
for (EKSource *source in eventStore.sources) {
if (source.sourceType == EKSourceTypeLocal) {
theSource = source;
break;
}
}
if (theSource) {
calendar.source = theSource;
} else {
NSLog(#"Error: Local source not available");
return;
}
NSError *error = nil;
BOOL result = [eventStore saveCalendar:calendar commit:YES error:&error];
if (result) {
NSLog(#"Saved calendar to event store.")
self.calendarIdentifier = calendar.calendarIdentifier;
} else {
NSLog(#"Error saving calendar: %#.", error);
}
// Delete Calendar
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKCalendar *calendar = [eventStore calendarWithIdentifier:self.calendarIdentifier];
if (calendar) {
NSError *error = nil;
BOOL result = [self.eventStore removeCalendar:calendar commit:YES error:&error];
if (result) {
NSLog(#"Deleted calendar from event store.");
} else {
NSLog(#"Deleting calendar failed: %#.", error);
}
}
I experienced the same. On iOS 5.0 it actually seems like the calendar is also used for reminders automatically.
You need to delete the calendar from the reminders app.
I think it may be a bug in iOS that you don't even get a notification when you unsuccessfully try to delete a programmatically created calendar from the calendar app.
There is a requirement in my application in which, when I take an appointment of a doctor for a particular day, that day should be added in iCal. and it should generate an alert view on that particular day.
So, I am not getting how to add an event in iCal. Please give me some answer for this.
The scenario is, I do have a string (NSString) of "date" and "notes" for that particular appointment. Then, how to insert all this information into iCal.
Code:
- (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;
}
// Overriding EKEventEditViewDelegate method to update event store according to user actions.
- (void)eventEditViewController:(EKEventEditViewController *)controller
didCompleteWithAction:(EKEventEditViewAction)action {
NSError *error = nil;
EKEvent *thisEvent = controller.event;
switch (action) {
case EKEventEditViewActionCanceled:
// Edit action canceled, do nothing.
break;
case EKEventEditViewActionSaved:
// When user hit "Done" button, save the newly created event to the event store,
// and reload table view.
// If the new event is being added to the default calendar, then update its
// eventsList.
if (self.defaultCalendar == thisEvent.calendar) {
[self.eventsList addObject:thisEvent];
}
[controller.eventStore saveEvent:controller.event span:EKSpanThisEvent error:&error];
[self.tableView reloadData];
break;
case EKEventEditViewActionDeleted:
// When deleting an event, remove the event from the event store,
// and reload table view.
// If deleting an event from the currenly default calendar, then update its
// eventsList.
if (self.defaultCalendar == thisEvent.calendar) {
[self.eventsList removeObject:thisEvent];
}
[controller.eventStore removeEvent:thisEvent span:EKSpanThisEvent error:&error];
[self.tableView reloadData];
break;
default:
break;
}
// Dismiss the modal view controller
[controller dismissModalViewControllerAnimated:YES];
}
// Set the calendar edited by EKEventEditViewController to our chosen calendar - the default calendar.
- (EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents:(EKEventEditViewController *)controller
{
EKCalendar *calendarForEdit = self.defaultCalendar;
return calendarForEdit;
}
I have used these functions and delegate methods. Please give me idea that, when the user gets alerted for the reminder, how to open up that information regarding that event?
You need the EventKit framework. You can ask the EKEventStore for its calendars, and then use those calendars to create a predicate that lets you find events that match the criteria you're looking for. Or you can create a new EKEvent object and save it into the event store.
Based on Apple Documentation, this has changed a bit as of iOS 6.0.
1) You should request access to the user's calendar via "requestAccessToEntityType:completion:" and execute the event handling inside of a block.
2) You need to commit your event now or pass the "commit" param to your save/remove call
Everything else stays the same...
Add the EventKit framework and #import to your code.
To add an event:
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (!granted) { return; }
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = #"Event Title";
event.startDate = [NSDate date]; //today
event.endDate = [event.startDate dateByAddingTimeInterval:60*60]; //set 1 hour meeting
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *err = nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
NSString *savedEventId = event.eventIdentifier; //this is so you can access this event later
}];
Remove the event:
EKEventStore* store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (!granted) { return; }
EKEvent* eventToRemove = [store eventWithIdentifier:savedEventId];
if (eventToRemove) {
NSError* error = nil;
[store removeEvent:eventToRemove span:EKSpanThisEvent commit:YES error:&error];
}
}];
I'm looking for a way to create a new Calendar on the iphone device programatically. I have been looking at Event Kit and it clearly states how to create a new event in a calendar and there is also a convenient way of gathering all the calendars in code, What I can't find is how to create a new one that is saved to the device.
Any ideas'
Check this kal repository for creating programmatically iphone calendar same as iCal
Check this method for creating programmatically event:
-(void)initCalendar {
// An array of 1 dictionary object, containing START and END values.
NSMutableArray* pvDict = [[NSMutableArray alloc] initWithContentsOfURL:[NSURL URLWithString:PV_URL ]];
// Check if the private view event already exists in the default calendar.
// Then set the calendar button state.
// Get a entry point to the Calendar database.
self.store = [[EKEventStore alloc ] init ];
// Get an array of all the calendars.
NSArray *calendars = store.calendars;
// Get the default calendar, set by the user in preferences.
EKCalendar *defaultCal = store.defaultCalendarForNewEvents;
// Find out if this calendar is modifiable.
BOOL isDefaultCalModifiable = defaultCal.allowsContentModifications ;
// Create an event in the default calendar.
self.event = [ EKEvent eventWithEventStore:store ];
self.event.title = CHELSEA_SPACE ;
self.event.location = CHELSEA_ADDRESS ;
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setDateFormat:#"yyy-MM-dd HH:mm:ss.S"];
NSString *startString = [[ pvDict objectAtIndex:0] objectForKey:#"starts" ];
NSDate *dateStart = [dateFormatter dateFromString:startString];
NSString *endString = [[ pvDict objectAtIndex:0] objectForKey:#"ends" ];
NSDate *dateEnd = [dateFormatter dateFromString:endString];
self.event.startDate = dateStart;
self.event.endDate = dateEnd;
self.event.calendar = defaultCal ;
// Alternative code to add 2.5 hours to start time.
// [[NSDate alloc] initWithTimeInterval:9000 sinceDate:event.startDate];
// Search for events which match this date/time start and end.
// Compare the matched events by event TITLE.
NSPredicate *predicate = [store predicateForEventsWithStartDate:event.startDate
endDate:event.endDate calendars:calendars];
NSArray *matchingEvents = [store eventsMatchingPredicate:predicate];
self.calendarButton.enabled = NO;
if( ! isDefaultCalModifiable ) {
// The default calendar is not modifiable
return ;
}
if ( [ matchingEvents count ] > 0 ) {
// There are already event(s) which match this date/time start and end.
// Check if this event is the PV
EKEvent *anEvent;
int j;
for ( j=0; j < [ matchingEvents count]; j++) {
anEvent = [ matchingEvents objectAtIndex:j ] ;
if([ CHELSEA_SPACE isEqualToString: anEvent.title ]) {
// PV event already exists in calendar.
return;
}
}
[ anEvent release ];
}
self.calendarButton.enabled = YES;
[ pvDict release ];
}
-(void)addEventToCalendar:(id)sender {
NSError *error;
BOOL saved = [self.store saveEvent:self.event span:EKSpanThisEvent error:&error];
NSLog(#"Saved calendar event = %#\n", (saved ? #"YES" : #"NO"));
self.calendarButton.enabled = NO;
}