I am trying to remove a EKCalendar that I have created inside my iOS app using the following method.
- (void)DeleteCalendar
{
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEntityType type = EKEntityTypeEvent;
NSArray *calendars = [eventStore calendarsForEntityType:type];
for (EKCalendar *thisCalendar in calendars){
NSLog(#"Calendar: %#", thisCalendar.title);
if ([thisCalendar.title isEqualToString:[NSString stringWithFormat:#"%#%#",CALENDARPREFIX, _currentCName]]) {
NSError *err;
[eventStore removeCalendar:thisCalendar commit:YES error:&err];
if (!err) {
NSLog(#"deleted %#", thisCalendar.title);
} else {
NSLog(#"%#", err.localizedDescription);
}
}
}
}
However when I run this method I get the following error from the last else statement.
That event does not belong to that event store
I have read that there is a bug in removeCalendar: however was hoping someone else may have experienced this and can help me fix the issue.
Related
I working in app using CloudKit. I'm implement a way to get deltas from CloudKit to my app (I'm using the public database). I get a response back from fetchNotificationChangesCompletionBlock block but I don't get a response back from notificationChangedBlock.
Here is my code:
-(void)checkForNewData
{
CKServerChangeToken *token = [[cloudKitToken helper] getCloudKitToken];
CKFetchNotificationChangesOperation *op = [[CKFetchNotificationChangesOperation alloc]
initWithPreviousServerChangeToken:token];
NSMutableArray *noteIds = [[NSMutableArray alloc] init];
op.notificationChangedBlock = ^(CKNotification *note)
{
CKNotificationID *noteId = note.notificationID;
[noteIds addObject:noteId];
if([note isKindOfClass:[CKQueryNotification class]]) {
CKQueryNotification *qNote = (CKQueryNotification *)note;
CKRecordID *changedRecordID = qNote.recordID;
NSLog(#"I got CKQueryNotification");
}
};
op.fetchNotificationChangesCompletionBlock = ^(CKServerChangeToken *token, NSError *error) {
NSLog(#"error %#", error.localizedDescription);
};
[[CKContainer defaultContainer] addOperation:op];
}
Any of you knows what I'm doing wrong or what is wrong with my code?
I'll really appreciate your help.
I want to delete all HKQuantitySamples that my app has saved in the Health App for a certain HKQuantityType, how would I do that?
I can see the function
deleteObject:withCompletion:
in the Apple Documentation, but I do not really understand how to use it. Can somebody show an example maybe?
EDIT: I now use the following code for deleting:
I have saved my food information as a HKCorrelation and set my Local Food ID in the Correlations metadata HKMetadataKeyExternalUUID key.
For deletion I am fetching all the HKCorrelation objects between startDate and endDate and then if one of these fetched objects matches the Local Food ID I am looking for:
- I delete every object in that Correlation,
- Followed by deleting the Correlation itself
HKCorrelationType *foodType = [HKObjectType correlationTypeForIdentifier:HKCorrelationTypeIdentifierFood];
NSPredicate *predicate = [HKQuery predicateForSamplesWithStartDate:startDate endDate:endDate options:HKQueryOptionNone];
HKSampleQuery *query = [[HKSampleQuery alloc] initWithSampleType:foodType predicate:predicate limit:HKObjectQueryNoLimit sortDescriptors:nil resultsHandler:^(HKSampleQuery *query, NSArray *results, NSError *error) {
if (!results) {
NSLog(#"An error occured fetching the user's tracked food. In your app, try to handle this gracefully. The error was: %#.", error);
return;
}
dispatch_async(dispatch_get_main_queue(), ^{
for (HKCorrelation *foodCorrelation in results) {
if([[foodCorrelation.metadata valueForKey:HKMetadataKeyExternalUUID] isEqualToString:food_id_I_want_to_delete]) {
NSSet *objs = foodCorrelation.objects;
for (HKQuantitySample *sample in objs) {
[self.healthStore deleteObject:sample withCompletion:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Success. delete sample");
}
else {
NSLog(#"delete: An error occured deleting the sample. In your app, try to handle this gracefully. The error was: %#.", error);
}
}];
}
[self.healthStore deleteObject:foodCorrelation withCompletion:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Success. delete %#", [foodCorrelation.metadata valueForKey:HKMetadataKeyExternalUUID]);
}
else {
NSLog(#"delete: An error occured deleting the Correlation. In your app, try to handle this gracefully. The error was: %#.", error);
}
}];
return;
}
}
});
}];
[self.healthStore executeQuery:query];
I have added an event on the default calendar on iPhone using the following code:
EKEventStore *store=[[EKEventStore alloc] init];
[store requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (!granted) {
return ;
}
EKEvent *event=[EKEvent eventWithEventStore:store];
event.title=#"This is the event";
event.startDate=[NSDate date];
event.endDate =[event.startDate dateByAddingTimeInterval:60*60];
event.allDay=YES;
NSURL *url=[NSURL URLWithString:#"http://www.google.com"];
event.URL=url;
[event setCalendar:[store defaultCalendarForNewEvents]];
NSError *errr=nil;
[store saveEvent:event span:EKSpanThisEvent commit:YES error:&errr]; // NSLog(#"%#",errr); // NSLog(#"%#",event.eventIdentifier);
}];
Now I want to delete this event.
The code I tried is this:
EKEventStore *store1=[[EKEventStore alloc]init];
NSPredicate *predicate=[store1 predicateForEventsWithStartDate:[[tableViewScheduleArray objectAtIndex:btn.tag] objectForKey:#"Schedule_Date"] endDate:[[tableViewScheduleArray objectAtIndex:btn.tag] objectForKey:#"Schedule_End_Time"] calendars:nil];
NSArray *arr=[store eventsMatchingPredicate:predicate];
dispatch_async(dispatch_get_main_queue(), ^{
[store1 removeEvent:[arr objectAtIndex:0] span:EKSpanThisEvent commit:YES error:nil];
});
It didn't work, but it didn't result in an error either.
I have tried several pieces of code from Stack Overflow but neither of them worked.
I got the solution,
It was a silly mistakes by me.
the property "store" which is not declare as strong.
as i changed it worked.
And Above code is working properly.
I have a recurring event in calendar. I'm delete a single event using this code [store removeEvent:event span:EKSpanThisEvent commit:YES error:&errorThis]; and this methods returns true but the event is not deleted from the calendar.
On EKCalendarItem Class reference using the property calendarItemExternalIdentifier you find this
Recurring event identifiers are the same for all occurrences. If you wish to differentiate between occurrences, you may want to use the start date
So you want delete only a recurrence you have to do something like this:
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate endDate:endDate calendars:calendars];
NSArray *theEvents = [eventStore eventsMatchingPredicate:predicate];
NSString *recurrenceEventIdentifier;
for(EKEvent * theEvent in theEvents)
{
if([theEvent.eventIdentifier isEqualToString: recurrenceEventIdentifier]
&& ![eventStore removeEvent:theEvent span:EKSpanThisEvent error:&error])
{
NSLog(#"Error in removing event: %#",error);
}
}
Your method instead, deletes only the first occurrence. If you want delete all recurring events just change "span" parameter in EKSpanFutureEvents.
EDIT: Now only deletes the matching recurrent event, not everything.
Please make sure you have only one instance of EKEventStore in singleton pattern in your app :
static EKEventStore *eventStore = nil;
+ (EKEventStore *)getEventStoreInstance
{
if (eventStore == nil){
#synchronized(self){
if (eventStore == nil){
eventStore = [[EKEventStore alloc] init];
}
}
}
return(eventStore);
}
I am trying to delete an event from the Calendar on user request. This is what I've come up with:
// Deleting Event
EKEventStore *eventStore = [[EKEventStore alloc] init];
EKEvent *event = [EKEvent eventWithEventStore:eventStore];
event.title = appDelegate.title1;
event.startDate = appDelegate.recAddDate;
event.endDate = appDelegate.currentDateName;
[event setCalendar:[eventStore defaultCalendarForNewEvents]];
NSError *err;
[eventStore removeEvent:event span:EKSpanThisEvent error:&err];
Below is the function I'm calling to remove the event from the event array. Items array is used to fetch events from iPhone calendar
- (BOOL)removeEvent:(EKEvent *)event span:(EKSpan)span error:(NSError **)error{
VoiceRecorderAppDelegate *appDelegate = (VoiceRecorderAppDelegate *)[[UIApplication sharedApplication] delegate];
[items removeObjectAtIndex:appDelegate.objectindexpath];
}
Firstly, save the eventId for the event while adding/saving events to the calendar.
[eventStore saveEvent:event span:EKSpanThisEvent error:&err];
NSString* str = [[NSString alloc] initWithFormat:#"%#", event.eventIdentifier];
[arrayofEventId addObject:str];
and then identify the event you want to remove ande then remove that event.
EKEventStore* store = [[EKEventStore alloc] init];
EKEvent* eventToRemove = [store eventWithIdentifier:[arrayofEventId objectAtIndex:i]];
if (eventToRemove != nil) {
NSError* error = nil;
[store removeEvent:eventToRemove span:EKSpanThisEvent error:&error];
}
Also don't forget to remove that event from arrayofEventId as well.
You can achieve this in the following ways:
By creating an NSpredicate using the date range withing which you
want to delete events, 86400 being the duration of a day in events, in
this piece of code I am deleting month old events. I am using a
dispatch queue, as the no. of events fetched may be large, and to keep the UI free.
First Create the event store and check access(access check required only iOS6 onwards):
- (void)addEventsToCalendar {
EKEventStore *eventStore = [[EKEventStore alloc] init];
if ([eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)]) {
//implementation for devices running OS version iOS 6.0 onwards.
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted) {
[self removeEventsFromStore:eventStore];
} else {
//perform for No Access using Error
}];
} else {
//implementation for devices running OS version lower than iOS 6.0.
[self removeEventsFromStore:eventStore];
}
}
Then remove events from the store:
- (void)removeEventsFromStore:(EKEventStore*)eventStore {
NSDate *startDate = [NSDate dateWithTimeIntervalSinceNow:-30 * 86400];
NSDate *endDate = [NSDate date];
dispatch_queue_t queue = dispatch_queue_create("com.arc.calendar", NULL);
dispatch_async(queue, ^{
NSArray *calendarArray = [NSArray arrayWithObject:[PWCCalendar getCalendarForEventStore:eventStore]];
NSPredicate *predicate = [eventStore predicateForEventsWithStartDate:startDate endDate:[NSDate dateWithTimeInterval:ONE_DAY_DURATION sinceDate:endDate] calendars:calendarArray];
NSArray *eventArray = [eventStore eventsMatchingPredicate:predicate];
for (EKEvent *event in eventArray) {
[eventStore removeEvent:event span:EKSpanThisEvent commit:YES error:NULL];
}
dispatch_async(dispatch_get_main_queue(), ^{
//Get the main Queue and perform UPdates
});
});
}
This is the Long way, use it to delete events in bulk. But if you need to delete only One event, then save the events identifier to `NSUserDefaults(after generating the event)
[eventStore saveEvent:event span:EKSpanThisEvent commit:YES error:NULL];
[[NSUserDefaults standardUserDefaults] setObject:[event eventIdentifier] forKey:#"Event ID"];
and then fetch it back while removing using
[eventStore eventWithIdentifier:#"Event ID"];
and then remove it from the store using
[eventStore removeEvent:event span:EKSpanThisEvent commit:YES error:NULL];
For more clarifications on the other methods to fetch events or calendar, pelase refer to EventStore docs: http://developer.apple.com/library/ios/#documentation/EventKit/Reference/EKEventStoreClassRef/Reference/Reference.html#//apple_ref/doc/uid/TP40009567 or to the Calendar and Reminder Programming guide: http://developer.apple.com/library/ios/#documentation/DataManagement/Conceptual/EventKitProgGuide/Introduction/Introduction.html#//apple_ref/doc/uid/TP40009765