EKRecurrenceRule not saved with EKEvent - objective-c

I have an app running, wich worked just fine until iOS11. Among many other things, it sets up EKEvents with recurrence. Those events still copy to the calendar as expected, but without the recurrence. And the recurrence vanishes after saving the event.
Thats how I'm doing it:
EKEventStore *newStore = [[EKEventStore alloc] init];
// define new EKEvent
EKEvent *newEvent = [EKEvent eventWithEventStore:newStore];
newEvent.calendar = [ResourceManager sharedResourceManager].selectedCalendar;
newEvent.allDay = TRUE;
newEvent.startDate = loopNSDate;
newEvent.endDate = loopNSDate;
newEvent.availability = EKEventAvailabilityFree;
EKRecurrenceRule *rule = [[EKRecurrenceRule alloc]
initRecurrenceWithFrequency:EKRecurrenceFrequencyDaily
interval:diensteInPlan
end:end];
NSArray *recurrenceRulesForDate = #[rule];
newEvent.recurrenceRules = recurrenceRulesForDate;
newEvent.title = #"EventTitle";
newEvent.notes = note;
NSError *error = nil;
[newStore saveEvent:newEvent span:EKSpanThisEvent error:&error];
NSLOGging the newEvent before "saveEvent..." shows an event with the correct recurrence. But NSLogging it afterwards shows the same event - but with (nill) as recurrence.
Am I missing something here? Many thanks in advance.

Related

CMAltimeter detect take off and landing

I would like to know how I can create a notification when the altitude is increasing and a notification when the altitude decreasing.
I already tried this code but I've no idea what to do next.
- (CMAltimeter *)altimeter {
if (!_altimeter) {
_altimeter = [[CMAltimeter alloc]init];
}
if ([CMAltimeter isRelativeAltitudeAvailable]) {
CMAltimeter* altimeter = [[CMAltimeter alloc] init];
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[altimeter startRelativeAltitudeUpdatesToQueue:queue withHandler:^(CMAltitudeData* altitudeData, NSError* error) {
}];
}
return _altimeter;
}
You pull out the data each time there's an update:
[altimeter startRelativeAltitudeUpdatesToQueue:queue
withHandler:^(CMAltitudeData* altitudeData, NSError* error)
{
// Put your data-handling code here -- for example,
// if your display has an element userRelAltitude
// that displays text:
float relAltitude;
relAltitude = altitudeData.relativeAltitude.floatValue;
self.userRelAltitude.text = [NSString stringWithFormat:#"%.0f m", relAltitude];
}];
Then you can compare each value to the previous one to see if it's increasing or decreasing and display an appropriate notification.

PHPhotoLibrary getting album and photo info

I am trying to get info on all the albums/photos using the PHPhotoLibrary. I barely know objective C, and i've looked at some tutorial/sample but couldn't find everything that I needed.
Here is a link to the sample code I based my code on.
https://developer.apple.com/library/ios/samplecode/UsingPhotosFramework/Introduction/Intro.html#//apple_ref/doc/uid/TP40014575-Intro-DontLinkElementID_2
So far I was able to get the albums name and identifier. And I am getting a list of photos, I am able to get their identifier as well, but not the filename. But if I put a break point in my fonction and look at my PHAsset pointer values, I can see the filename there (inside _filename), but if I try to call the variable with the filename in it, the variable does not exist.
So if anyone can provide a sample code to get all info on albums/photos/thumbnail that would be awesome. Or just getting the filename would be a good help.
Here is the code I have tried so far:
-(void)awakeFromNib{
NSMutableArray *allPhotos = self.getAllPhotos;
for (int x = 0; x < allPhotos.count; x ++)
{
PHAsset *photo = [self getPhotoAtIndex:x];
PHAssetSourceType source = photo.sourceType;
NSString *id = photo.localIdentifier;
NSString *description = photo.description;
NSUInteger height = photo.pixelHeight;
NSUInteger width = photo.pixelWidth;
NSLog(#"Test photo info");
}
}
-(PHAsset*) getPhotoAtIndex:(NSInteger) index
{
return [self.getAllPhotos objectAtIndex:index];
}
-(NSMutableArray *) getAllPhotos
{
NSMutableArray *photos = [[NSMutableArray alloc] init];
PHFetchOptions *allPhotosOptions = [[PHFetchOptions alloc] init];
allPhotosOptions.sortDescriptors = #[[NSSortDescriptor sortDescriptorWithKey:#"creationDate" ascending:YES]];
PHFetchResult *allPhotos = [PHAsset fetchAssetsWithOptions:allPhotosOptions];
PHFetchResult *fetchResult = #[allPhotos][0];
for (int x = 0; x < fetchResult.count; x ++) {
PHAsset *asset = fetchResult[x];
photos[x] = asset;
}
return photos;
}
As you can see, I can get the image height and width, its id, but cannot get the url to it.
I have found a way to get the url of my photo.
-(void)getImageURL:(PHAsset*) asset
{
PHContentEditingInputRequestOptions *options = [[PHContentEditingInputRequestOptions alloc] init];
[options setCanHandleAdjustmentData:^BOOL(PHAdjustmentData *adjustmentData) {
return [adjustmentData.formatIdentifier isEqualToString:AdjustmentFormatIdentifier] && [adjustmentData.formatVersion isEqualToString:#"1.0"];
}];
[asset requestContentEditingInputWithOptions:options completionHandler:^(PHContentEditingInput *contentEditingInput, NSDictionary *info)
{
NSURL* url = contentEditingInput.fullSizeImageURL;
}];
}
Filenames in the Photos library are an implementation detail and subject to change. There are various private API for discovering them (or ways to use valueForKey or other public introspection APIs to find where they're hidden), they aren't something to be relied upon. In particular, an asset that's been edited is likely to have a different filename than the original.
What do you need a filename/URL for? If you're just uniquely identifying the asset across launches of your app, use localIdentifier. If you're showing it to the user... why? Something like IMG_0234.jpg vs IMG_5672.jpg has little meaning to the average user.
To fetch the assets in a specific album, use fetchAssetsInAssetCollection:options:. To fetch the album(s) containing a specific asset, use fetchAssetCollectionsContainingAsset:withType:options:. To discover the list(s) of albums, use other APIs on PHAssetCollection and its superclass PHCollection.

Error getting shared calendar invitations for entity types 3, Xcode 6.1.1. EKCalender, EKSource, EKEventstore and Objective C

I am developing calendar app. I am trying to save EKEvent using assigned EKCalender. But when I try to run following code it gives me error. Please help
-(BOOL)createEventWithTitle:(NSString *)paramTitle startDate:(NSDate *)paramStartDate endDate:(NSDate *)paramEndDate inCalendar:(EKCalendar *)paramCalendar inEventStore:(EKEventStore *)paramStore notes:(NSString *)paramNotes
{
BOOL result = NO;
//paramCalendar = [self.eventStoreiReportShifts defaultCalendarForNewEvents];
if (self.eventsAccessGranted) {
NSArray *caledars = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
self.selectedCalendarEventKitIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:#"eventkit_cal_identifiers_string"];
for(EKCalendar *aCal in caledars){
if([aCal.calendarIdentifier isEqualToString:self.selectedCalendarEventKitIdentifier]){
paramCalendar = [self.eventStore calendarWithIdentifier:[[NSUserDefaults standardUserDefaults] objectForKey:#"eventkit_cal_identifiers_string"]];
}
}
for (EKSource *source in self.eventStore.sources) {
if (source.sourceType == EKSourceTypeCalDAV) {
paramCalendar.source = source;
break;
} else if(source.sourceType == EKSourceTypeLocal){
paramCalendar.source = source;
break;
}
}
}else{
return NO;
}
/* If a calendar does not allow modification of its contents
then we can not insert an event into it */
if (paramCalendar.allowsContentModifications == NO) {
NSLog (# "\n\n The selected calendar does not allow modifications.");
return NO;
}
/* Create an event */
EKEvent * event = [EKEvent eventWithEventStore:paramStore];
event.calendar = paramCalendar;
/* Set the properties of the event such as its title,
start date / time, end date / time, etc. */
event.title = paramTitle;
event.notes = paramNotes;
event.startDate = paramStartDate;
event.endDate = paramEndDate;
/* Finally, save the event into the calendar */
NSError * saveError = nil;
result = [paramStore saveEvent:event
span:EKSpanThisEvent
error:&saveError];
if (result == NO) {
NSLog (# "\n\n An error occurred = %#", saveError);
}
return result;
}
above code gives following error
CalendarCalculations[1668:45103]
Error getting shared calendar invitations for entity types 3 from
daemon: Error Domain=EKCADErrorDomain Code=1013
"The operation couldn’t be completed. (EKCADErrorDomain error 1013.)"
how can I get rid of it please?
I had the same problem in my app. I noticed the error occurs when calendarWithIdentifier method is called.
EKCalendar *selectedCalendar = [self.eventStore calendarWithIdentifier:selectedCalendarIdentifier];
I don't know exactly why it occurs but I guess it happens when you don't have any shared calendar in your device. Here is a link About shared iCloud calendars
I found the solution here and i fixed it in my app with next code snippet:
EKCalendar *selectedCalendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.eventStore];
NSString *selectedCalendarIdentifier = [[NSUserDefaults standardUserDefaults] objectForKey:#"selectedCalendarIdentifier"];
//instead of getting calendar by identifier
//get all calendars and check matching in the cycle
NSArray *allCalendars = [self.eventStore calendarsForEntityType:EKEntityTypeEvent];
for (EKCalendar *calendar in allCalendars) {
if ([calendar.calendarIdentifier isEqualToString:selectedCalendarIdentifier]) {
selectedCalendar = calendar;
break;
}
}
Off course it's not very good way but error disappeared.
Hope it will help you ;)
Another cause for this error is to use the bit mask EKEntityMaskEvent instead of the type EKEntityTypeEvent for the entity type parameter creating the calendar.
If you try to create the calendar such as:
EKCalendar *calendar = [EKCalendar calendarForEntityType:EKEntityMaskEvent eventStore:self.eventStore];
Then the calendar is well returned with an identifier, but the calendar seems not to be valid and it cannot be saved although no error is get. No event cannot be added to it. And the calendarWithIdentifier returns nil.
The right syntax is using EKEntityTypeEvent such as:
EKCalendar *calendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.eventStore];
Old question but, for reference, I had this problem when I switched from working with Reminders to Calendar events. I forgot to change the entity type in all the places.
Specifically, I was loading the status of my permissions for EKEntityTypeReminder with
EKAuthorizationStatus authorizationStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeReminder];
and latter asking the user permission for EKEntityTypeEvent with
[self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (error == nil) {
// Store the returned granted value.
} else {
NSLog(#"%#", [error localizedDescription]);
}
}];
So, the solution was to change the checking of status of my permissions to this:
EKAuthorizationStatus authorizationStatus = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent];

Need assistance regarding using the xep-0184

I am using robbiehanson/XMPPFramework for my current project, I can send and receive messages to people in my roster, but now I have to implement message delivery status. I know the xep its 0184 and I have also included in my project, I am having difficulty utilizing it.
I read in xep-0184 document that request element must also included in message, so here is my code:
#import "XMPPMessage+XEP_0184.h"
.
.
.
NSXMLElement *body = [NSXMLElement elementWithName:#"body"];
[body setStringValue:messageStr];
NSXMLElement *request = [NSXMLElement elementWithName:#"request" xmlns:#"urn:xmpp:receipts"];
NSXMLElement *message = [NSXMLElement elementWithName:#"message"];
[message addAttributeWithName:#"type" stringValue:#"chat"];
[message addAttributeWithName:#"to" stringValue:[defaults objectForKey:#"chatWith"]];
[message addChild:body];
[message addChild:request];
.
.
.
XMPPMessage *xm = [[XMPPMessage alloc]init];
NSLog(#"..1..%d",[xm hasReceiptRequest]); // Result = 0
NSLog(#"..2..%d",[xm hasReceiptResponse]); // Result = 0
NSLog(#"..3..%#",[xm extractReceiptResponseID]); // Result = (null)
NSLog(#"..4..%#",[xm generateReceiptResponse]); // Result = <message><received xmlns="urn:xmpp:receipts"></received></message>
Please help how do i get a message delivery status.
I think you forgot to add the module itself.
When you want to add an XMPPModule like XMPPMessageDeliveryReceipts you should add it to the XMPPStream object first, then you can use its functions.
Do the following:
// Setup Message Delivery Recipts Object
XMPPMessageDeliveryReceipts* xmppMessageDeliveryRecipts = [[XMPPMessageDeliveryReceipts alloc] initWithDispatchQueue:dispatch_get_main_queue()];
xmppMessageDeliveryRecipts.autoSendMessageDeliveryReceipts = YES;
xmppMessageDeliveryRecipts.autoSendMessageDeliveryRequests = YES;
[xmppMessageDeliveryRecipts activate:xmppStream];
When xmppStream is your main XMPPFramework object.
Hope i helped.

Adding CalTasks from an NSArray

I have an NSArray of Strings and what I want to do is create a new CalTask (for the calendar store) for every String, I want the Name of the task to be the string that is being added, the Priority and Due Date to be set in the code.
For example I have an array with the Strings To-Do 1, TD 2, TD 3.
So I want to create 3 CalTasks, the first one with the Name To-Do 1 and the second with the name TD 2 etc. See what I'm talking about. But I want all the Priorities and Due Dates to be the Same.
What you can do is loop over the NSArray and create and add a new CalTask with a predefined priority and due date:
// Set up the array
NSArray *array = [NSArray arrayWithObjects:#"TD1", #"TD2", #"TD3", nil];
// Get the calendar
CalCalendarStore *store = [CalCalendarStore defaultCalendarStore];
CalCalendar *calendar = [[store calendars] objectAtIndex:0];
// Note: you can change which calendar you're adding to by changing the index or by
// using CalCalendarStore's -calendarWithUID: method
// Define priority and due date
NSDate *dueDate = [NSDate date]; // By default due now - change as needed
CalPriority priority = CalPriorityMedium; // By default medium - change as needed
// Loop, adding tasks
for(NSString *title in array) {
// Create task
CalTask *task = [CalTask task];
task.dueDate = dueDate;
task.priority = priority;
task.title = title;
task.calendar = calendar;
// Save task
NSError *error = nil;
if(![store saveTask:task error:&error]) {
// Diagnostic error handling
NSAlert *anAlert = [NSAlert alertWithError:error];
[anAlert runModal];
}
}
Have a look at the Calendar Store Programming Guide.