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.
Related
Hi I have integrated google Dive with my app using Dr. Edit sample code from google drive. But i am not able to view all the files, which are stored in my Google Drive account.
// I have tried this
-(void)getFileListFromSpecifiedParentFolder
{
GTLQueryDrive *query2 = [GTLQueryDrive queryForChildrenListWithFolderId:#"root"];
query2.maxResults = 1000;
[self.driveService executeQuery:query2
completionHandler:^(GTLServiceTicket *ticket,
GTLDriveChildList *children, NSError *error)
{
NSLog(#"\nGoogle Drive: file count in the folder: %d", children.items.count);
if (!children.items.count)
{
return ;
}
if (error == nil)
{
for (GTLDriveChildReference *child in children)
{
GTLQuery *query = [GTLQueryDrive queryForFilesGetWithFileId:child.identifier];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *file,
NSError *error)
{
NSLog(#"\nfile name = %#", file.originalFilename);}];
}
}
}];
}
//I want to Display All content in NSLog...
1. How to get all files from Google Drive.
First in viewDidLoad: method check for authentication
-(void)viewDidLoad
{
[self checkForAuthorization];
}
And here is the definition of all methods:
// This method will check the user authentication
// If he is not logged in then it will go in else condition and will present a login viewController
-(void)checkForAuthorization
{
// Check for authorization.
GTMOAuth2Authentication *auth =
[GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:kClientId
clientSecret:kClientSecret];
if ([auth canAuthorize])
{
[self isAuthorizedWithAuthentication:auth];
}
else
{
SEL finishedSelector = #selector(viewController:finishedWithAuth:error:);
GTMOAuth2ViewControllerTouch *authViewController =
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientId
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:finishedSelector];
[self presentViewController:authViewController animated:YES completion:nil];
}
}
// This method will be call after logged in
- (void)viewController:(GTMOAuth2ViewControllerTouch *)viewController finishedWithAuth: (GTMOAuth2Authentication *)auth error:(NSError *)error
{
[self dismissViewControllerAnimated:YES completion:nil];
if (error == nil)
{
[self isAuthorizedWithAuthentication:auth];
}
}
// If everthing is fine then initialize driveServices with auth
- (void)isAuthorizedWithAuthentication:(GTMOAuth2Authentication *)auth
{
[[self driveService] setAuthorizer:auth];
// and finally here you can load all files
[self loadDriveFiles];
}
- (GTLServiceDrive *)driveService
{
static GTLServiceDrive *service = nil;
if (!service)
{
service = [[GTLServiceDrive alloc] init];
// Have the service object set tickets to fetch consecutive pages
// of the feed so we do not need to manually fetch them.
service.shouldFetchNextPages = YES;
// Have the service object set tickets to retry temporary error conditions
// automatically.
service.retryEnabled = YES;
}
return service;
}
// Method for loading all files from Google Drive
-(void)loadDriveFiles
{
GTLQueryDrive *query = [GTLQueryDrive queryForFilesList];
query.q = [NSString stringWithFormat:#"'%#' IN parents", #"root"];
// root is for root folder replace it with folder identifier in case to fetch any specific folder
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFileList *files,
NSError *error) {
if (error == nil)
{
driveFiles = [[NSMutableArray alloc] init];
[driveFiles addObjectsFromArray:files.items];
// Now you have all files of root folder
for (GTLDriveFile *file in driveFiles)
NSLog(#"File is %#", file.title);
}
else
{
NSLog(#"An error occurred: %#", error);
}
}];
}
Note: For get full drive access your scope should be kGTLAuthScopeDrive.
[[GTMOAuth2ViewControllerTouch alloc] initWithScope:kGTLAuthScopeDrive
clientID:kClientId
clientSecret:kClientSecret
keychainItemName:kKeychainItemName
delegate:self
finishedSelector:finishedSelector];
2. How to download a specific file.
So for this you will have to use GTMHTTPFetcher. First get the download URL for that file.
NSString *downloadedString = file.downloadUrl; // file is GTLDriveFile
GTMHTTPFetcher *fetcher = [self.driveService.fetcherService fetcherWithURLString:downloadedString];
[fetcher beginFetchWithCompletionHandler:^(NSData *data, NSError *error)
{
if (error == nil)
{
if(data != nil){
// You have successfully downloaded the file write it with its name
// NSString *name = file.title;
}
}
else
{
NSLog(#"Error - %#", error.description)
}
}];
Note: If you found "downloadedString" null Or empty just have look at file.JSON there are array of "exportsLinks" then you can get the file with one of them.
3. How to upload a file in specific folder: This is an example of uploading image.
-(void)uploadImage:(UIImage *)image
{
// We need data to upload it so convert it into data
// If you are getting your file from any path then use "dataWithContentsOfFile:" method
NSData *data = UIImagePNGRepresentation(image);
// define the mimeType
NSString *mimeType = #"image/png";
// This is just because of unique name you can give it whatever you want
NSDateFormatter *df = [[NSDateFormatter alloc] init];
[df setDateFormat:#"dd-MMM-yyyy-hh-mm-ss"];
NSString *fileName = [df stringFromDate:[NSDate date]];
fileName = [fileName stringByAppendingPathExtension:#"png"];
// Initialize newFile like this
GTLDriveFile *newFile = [[GTLDriveFile alloc] init];
newFile.mimeType = mimeType;
newFile.originalFilename = fileName;
newFile.title = fileName;
// Query and UploadParameters
GTLUploadParameters *uploadParameters = [GTLUploadParameters uploadParametersWithData:data MIMEType:mimeType];
GTLQueryDrive *query = [GTLQueryDrive queryForFilesInsertWithObject:newFile uploadParameters:uploadParameters];
// This is for uploading into specific folder, I set it "root" for root folder.
// You can give any "folderIdentifier" to upload in that folder
GTLDriveParentReference *parentReference = [GTLDriveParentReference object];
parentReference.identifier = #"root";
newFile.parents = #[parentReference];
// And at last this is the method to upload the file
[[self driveService] executeQuery:query completionHandler:^(GTLServiceTicket *ticket, id object, NSError *error) {
if (error){
NSLog(#"Error: %#", error.description);
}
else{
NSLog(#"File has been uploaded successfully in root folder.");
}
}];
}
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 have this method which adds events to native iphone calendar.
It is already adding monthly reminders successfully - but I want to force any monthy reminders to fall into week days (not weekends).
The NSDictionary model is simply
Id:
Start_Date__c
Finish_Date__c
Payment_Interval__c = Monthly
- (void)addRecurringEventsForPartnership:(NSDictionary *)dict{
ENTER_METHOD;
NSError *error = nil;
EKEvent *startEvent = [EKEvent eventWithEventStore:self.eventStore];
startEvent.calendar = self.defaultCalendar;
startEvent.availability = EKEventAvailabilityFree;
startEvent.startDate = [NSDate dateWithLongFormatString:[dict valueForKey:#"Start_Date__c"]];
startEvent.allDay = YES;
// startEvent.endDate = [startEvent.startDate dateByAddingTimeInterval:30*60];
startEvent.title = [dict theNameValue];
//http://stackoverflow.com/questions/7718006/xcode-why-is-my-event-not-being-added-to-the-calendar
if ([startEvent.startDate isEqualToDate:startEvent.endDate]) {
startEvent.endDate = [startEvent.startDate dateByAddingTimeInterval:30*60];;
}
// if
if ([[dict valueForKey:#"Payment_Interval__c"] isEqualToString:#"Monthly"]) {
EKRecurrenceFrequency freq = EKRecurrenceFrequencyMonthly;
int recurrenceInterval = 1;
EKRecurrenceRule *rule = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:freq interval:recurrenceInterval end:nil];
startEvent.recurrenceRule = rule;
startEvent.notes = [NSString stringWithFormat:#"Id:%#",[dict valueForKey:#"Id"]];
// [self.eventStore removeEvent:startEvent span:EKSpanThisEvent error:&error];
[self.eventStore saveEvent:startEvent span:EKSpanThisEvent error:&error];
if (error != nil)
{
DLog(#"WARNING:%#",error.description);
// TODO: error handling here
}
}
// DLog(#"startEvent.endDate:%#",startEvent.endDate);
EKEvent *finishEvent = [EKEvent eventWithEventStore:self.eventStore];
finishEvent.calendar = self.defaultCalendar;
finishEvent.availability = EKEventAvailabilityFree;
finishEvent.startDate = [NSDate dateWithLongFormatString:[dict valueForKey:#"Finish_Date__c"]];
finishEvent.allDay = YES;
finishEvent.title = [NSString stringWithFormat:#"%# - Finish",[dict theNameValue]];
finishEvent.notes = [NSString stringWithFormat:#"Id:%#",[dict valueForKey:#"Id"]];
[self.eventStore saveEvent:finishEvent span:EKSpanThisEvent error:&error];
if (error != nil)
{
DLog(#"WARNING:%#",error.description);
// TODO: error handling here
}
}
Couldn't you use NSDateFormatter to get the numeric day of the week and then adjust by subtracting or adding 1 or 2 depending on which day it returned?
[dateFormatter setDateFormat:#"c"];
Will return numeric (1-7) day of the week, I believe
Here's something that works (at least in iOS7, didn't test on other systems):
EKRecurrenceRule *er = [[EKRecurrenceRule alloc] initRecurrenceWithFrequency:EKRecurrenceFrequencyMonthly interval:1
daysOfTheWeek:#[[EKRecurrenceDayOfWeek dayOfWeek:2], // Monday
[EKRecurrenceDayOfWeek dayOfWeek:3], // Tuesday
[EKRecurrenceDayOfWeek dayOfWeek:4], // Wednesday
[EKRecurrenceDayOfWeek dayOfWeek:5], // Thursday
[EKRecurrenceDayOfWeek dayOfWeek:6]] // Friday
daysOfTheMonth:#[#1, #2]
monthsOfTheYear:nil weeksOfTheYear:nil daysOfTheYear:nil setPositions:nil end:nil];
event.recurrenceRules = #[er];
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 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);
}
}