I am trying to add event in iOS app using Event kit with following code:
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (!granted) { return; }
dispatch_async(dispatch_get_main_queue(), ^{
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = eventName;
event.startDate = [NSDate dateFromString:[NSString stringWithFormat:#"%# %#",[arrEvent objectAtIndex:1],[arrEvent objectAtIndex:2]] withFormat:#"MM/dd/yyyy HH:mm"];
event.endDate = [NSDate dateFromString:[NSString stringWithFormat:#"%# %#",[arrEvent objectAtIndex:1],[arrEvent objectAtIndex:3]] withFormat:#"MM/dd/yyyy HH:mm"];
[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
NSLog(#"%#",savedEventId);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Event added to calendar" message:nil delegate:self cancelButtonTitle:#"OK" otherButtonTitles:#"View Calendar", nil];
alert.tag = 101;
[alert show];
});
}];
But I am getting granted as false so it doesn't add the event. It is not working in my simulator and device both, even after I reset my simulator. Same code works in another app of mine. Can someone please suggest me what I should do?
Edit: Error is always nil
When app launched for first time, a message asking for permissions will be shown to the user, and app will be able to access the calendar if only the user granted permission. In your case you have declined permission for calendar.
For fixing this issue, Go to Settings -> -> Allow to access calendar = YES.
Seems like you're requesting to get the access every time. You should better check the authorisation status first and if it's not determined, only then request for the authorisation. First check this using "authorizationStatusForEntityType" and create a new method to save the event, not inside "requestAccessToEntityType".
Related
I am trying to open calendar with specific event, I have added events programmatically and all the IDs of these event are persistent.
This is how i add event
-(IBAction)addEvent:(id)sender{
EKEventStore *store = [[EKEventStore alloc]init];
[store requestAccessToEntityType:EKEntityTypeReminder completion:^(BOOL granted, NSError *error) {
if (!granted) { return; }
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = #"Demo Title";
NSDateComponents *comps=[[NSDateComponents alloc]init];
[comps setDay:4];
[comps setMonth:10];
[comps setYear:2016];
[comps setHour:12];
[comps setMinute:1];
NSDate *date=[[[NSCalendar alloc]initWithCalendarIdentifier:NSCalendarIdentifierGregorian] dateFromComponents:comps];
_date=date;
event.startDate = date;
event.endDate=date;
event.notes=#"This is event description";
EKAlarm *alarm=[EKAlarm alarmWithAbsoluteDate:date];
[event addAlarm:alarm];
event.calendar = [store defaultCalendarForNewEvents];
NSError *err=nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
}];
}
The event is added successfully and i'm also able to open calendar app but the thing is i can't navigate inside the event detail in calendar
here is how i open calendar
-(IBAction)openCalender:(id)sender{
NSInteger interval = [_date timeIntervalSinceReferenceDate];
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"calshow:%ld?eventid=%#", (long)interval,_eventID]];
NSLog(#"%#",url);
[[UIApplication sharedApplication] openURL:url];
}
What i want is in below screenshot
What i'm getting is
any idea?
To answer my own question, this isn't possible with any of public API
I searched over a year but this is not possible with any public API, but i guess there might be some private API to do this (and probably doing that will get our app rejected).
Widget of calendar app is doing the same what i want to do but it's Apple's API wont allow us to use it. lol
I really don't think there's a way to do this. Even when creating a new calendar event from the default Mail app opens the calendar day view. If this functionality was possible I'm sure they would have at least implemented it in the default mail app.
I am attempting to save an event into the calendar, from my application.
My code works for iOS 7, but on iOS 6, it returns No calendar has been set.
The application prompts for user to grant access to the calendar, on iOS 7.
But no such prompt appears for iOS 6. Although the application is granted access in the Settings-> Privacy -> Calendar.
And yes, I have already implemented the requestAccessToEntityType:completion:.
Here is my code snippet.
EKEventStore *objStore = [[EKEventStore alloc]init];
if ([objStore respondsToSelector:#selector(requestAccessToEntityType:completion:)])
{
// iOS 6 and later
[objStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
dispatch_async(dispatch_get_main_queue(), ^{
if (granted)
{
// code here for when the user allows your app to access the calendar
EKEvent *calEvent = [EKEvent eventWithEventStore:objStore];
calEvent.title = mstrTitleEvent;
calEvent.startDate = self.dateToBeSet;
calEvent.endDate = self.dateToBeSet;
calEvent.calendar = objStore.defaultCalendarForNewEvents;
EKAlarm *objAlarm = [EKAlarm alarmWithAbsoluteDate:self.dateToBeSet];
[calEvent addAlarm:objAlarm];
NSError *error;
BOOL _bStatus = [objStore saveEvent:calEvent span:EKSpanThisEvent commit:YES error:&error];
UIAlertView *alertV;
if(_bStatus)
{
alertV = [[UIAlertView alloc]initWithTitle:#"Congratulations" message:#"Saved To Calendar" delegate:nil cancelButtonTitle:#"Right On!" otherButtonTitles:nil];
[alertV show];
}
else
{
alertV = [[UIAlertView alloc]initWithTitle:#"Alert" message:[NSString stringWithFormat:#"Error saving to calendar, with error %#.",[error localizedDescription]] delegate:nil cancelButtonTitle:#"Cancel" otherButtonTitles:nil];
[alertV show];
}
}
else
{
// code here for when the user does NOT allow your app to access the calendar
UIAlertView *alertV = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Please grant access to the calendar, and try again later." delegate:nil cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alertV show];
}
});
}];
}
Just managed to somehow find a solution for my problem.
I had to navigate from one page to another, so posting the link to the two pages.
First ->
https://discussions.apple.com/message/16497282#16497282
Then, from there to ->
https://discussions.apple.com/message/16479587#16479587
I had to go into Settings>iCloud> and turn on Calendars.
After that, I tried to attempt and run my code, and it was working well and fine again.
Do attempt this, if you facing a similar problem.
I was working on iPad 2, and with iOS 6.1.3 installed on the device.
Amazing I am testing my code on two different devices, one it works fine and the other it will not work. Just looked in setting and the one with it not working has iCloud calendar and reminders turned off, just turn them on and it all works now... this has to be a bug
I would like to have the actual event, which is synchronised on my calendar app.
The actual event is the event which is happening now.
I would like, at first, to make an app which tells me how much time remains before the end of my event.
The event is my calendar synchronized to my iphone.
In my Main.StoryBoard, I declared a Label:
#property (strong, nonatomic) IBOutlet UILabel *currentEvent;
I declared a EKEventStore:
EKEventStore *store = [[EKEventStore alloc] init];
From now, I know how to create an event, with start date, end date.. but I would like to retrieve the information from my current event, to be able to do: endDate - timeActual;
Next, in my Label, it will be written : 57 minutes before the end of the event.
NSLog(#"%i minutes before the end of the event.", remainTime );
I don't know if I'm clear, tell me if you don't understand what I'm asking?
Thank you for your help! :)
[Update]
I know how to have the identier of my calendar :
EKEventStore *store = [[EKEventStore alloc] init];
store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (!granted)
NSLog(#"Access to store not granted");
}];
NSArray *calendars = [store calendarsForEntityType:EKEntityTypeEvent];
for (EKCalendar *calendar in calendars)
{
NSLog(#"Calendar = %#", calendar.description);
self.currentEvent.text = [NSString stringWithFormat:#"%#", calendar.calendarIdentifier];
}
EKCalendar *myCalendar = calendars[0];
NSLog(#"My Calendar = %#", myCalendar);
EKEvent *actualEvent = [EKEvent eventWithEventStore:store];
I know how to set event on my calendar, but no have events which are in my calendar!
Have you got any ideas ?
In my Application i need to attach(show iphone inbuilt calender) in-built iphone calendar on the UIButton action. More, The text from my UIViewControllers UILabel, I need attach that text in iphones in built calendar as reminder, where user is free to select date according his need.
I had found like EventKIt framework may be useful to me, But i am not sure. And i am also not familiar with EventKit framework.
Just Use this example with EventKit framwork.
-(IBAction)buttonAction:(id)sender
{
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEventStore *eventStore = [[[EKEventStore alloc] init] autorelease];
if([eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)]) {
// iOS 6 and later
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted){
//---- codes here when user allow your app to access theirs' calendar.
[self performCalendarActivity:eventStore];
}else
{
//----- codes here when user NOT allow your app to access the calendar.
}
}];
}
else {
//---- codes here for IOS < 6.0.
[self performCalendarActivity:eventStore];
}
}
-(void)performCalendarActivity:(EKEventStore *)eventStore
{
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = #"EVENT TITLE";
event.startDate = [[NSDate alloc] init];
event.endDate = [[NSDate alloc] initWithTimeInterval:600 sinceDate:event.startDate];
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
NSError *err;
[eventStore saveEvent:event span:EKSpanThisEvent error:&err];
}
Don't forget to import #import <EventKit/EventKit.h> to your view controller.
I am simply wanting to add an event to the device's calendar.
I'm using:
__weak ProgramViewController *weakSelf = self;
EKEventStore *store = [[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error)
{
if (error)
NSLog(#"EKEventStore error = %#", error);
if (granted)
{
NSLog(#"EKEvent *event ");
EKEvent *event = [EKEvent eventWithEventStore:store];
event.title = weakSelf.program.title;
event.location = weakSelf.program.locationPublic;
event.startDate = weakSelf.program.startTime;
event.endDate = weakSelf.program.endTime;
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *err = nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&err];
if (err)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Calendar Error" message:err.localizedDescription delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
else
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Added" message:#"Calendar event added." delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertView show];
}
}
}];
and in iOS 6 it can take 6/7 seconds (iPhone 4) and on iOS 7 (on an iPhone 5S) it takes ~10 seconds. Is this normal behaviour? If not what am I doing wrong?
I had the same issue. Thanks to Jasper's answer, I got thinking about queues. Try this:
if (!err)
{
dispatch_async(dispatch_get_main_queue(),
^{
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"event added", nil) message:nil delegate:nil cancelButtonTitle:NSLocalizedString(#"ok", nil) otherButtonTitles:nil] show];
});
}
Here's why this is needed (see emphasis)
Discussion
In iOS 6 and later, requesting access to an event store
asynchronously prompts your users for permission to use their data.
The user is only prompted the first time your app requests access to
an entity type; any subsequent instantiations of EKEventStore uses
existing permissions. When the user taps to grant or deny access, the
completion handler will be called on an arbitrary queue. Your app is
not blocked while the user decides to grant or deny permission.
Since UIAlertView is UIKit, and UIKit always requires the main thread, any other arbitrary thread will crash or lead to unpredictable behaviour.
https://developer.apple.com/library/ios/documentation/EventKit/Reference/EKEventStoreClassRef/Reference/Reference.html
According to the docs: "An EKEventStore object requires a relatively large amount of time to initialize and release." . . so you should dispatch this on a background queue.
Also, oddly, it takes longer on the main queue than the background queue - not sure why this is!