Access Calendar UIDocumentInteractionController

I have an ics (Calendar) file that I open with a UIDocumentInteractionController using presentOptionsMenuFromRect: When this is done, the Open menu looks like this .

As you can see, there is no "add to calendar" option. Here's what gets me: I use the exact same code for the .vcf (card card) file, and it works as expected with the Open contacts option available.

Do I really miss some permission in my Info.plist to access the calendar? Why UIDocumentInteractionController n't the UIDocumentInteractionController correctly handle the .ics file type, but .vcf working fine? These two types of files are very similar. In the options menu, if I send the ics file to myself and open it from the mail application, it will read it perfectly, and I can add events to my calendar, so I know that the data is valid. I searched high and low for a solution, and no one seems to know why access to the calendar does not work. Some questions that I have encountered remain unanswered:

Unable to add ics file to calendar

How can I set the UIDocumentInteractionController Calendar as an option to open a .ics file?

If Apple does this on purpose, the only reason I can think of is that they would prefer developers to use EventKit to add events to the Calendar. If so, this decision is rather complicated. Any understanding of this problem would be greatly appreciated.

+1
source share
1 answer

I ended up downloading the .ics file via ( https://github.com/KiranPanesar/MXLCalendarManager ). Then I was able to use EventKit to parse the downloaded .ics file in EKEvent and open it via EKEventEditViewController ( https://developer.apple.com/library/prerelease/ios/samplecode/SimpleEKDemo/Listings/Classes_RootViewController_m.html ). A bit around, but it seemed to work. This is how I set up my webview controller class that implements this:

 @interface WebViewController : UIViewController <UIWebViewDelegate, EKEventEditViewDelegate> { // EKEventStore instance associated with the current Calendar application @property (nonatomic, strong) EKEventStore *eventStore; // Default calendar associated with the above event store @property (nonatomic, strong) EKCalendar *defaultCalendar; @end @implementation WebViewController - (void)viewDidLoad { [super viewDidLoad]; ... // Initialize the event store self.eventStore = [[EKEventStore alloc] init]; } - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { NSURL *url = [request URL]; NSString *path = [url absoluteString]; NSRange range = [path rangeOfString:@".ics" options:NSCaseInsensitiveSearch]; if (range.length > 0) { [self checkCalendarAndAddEvent:url]; return NO; } [UIApplication sharedApplication].networkActivityIndicatorVisible = YES; return YES; } -(void)checkCalendarAndAddEvent:(NSURL*)url { EKAuthorizationStatus status = [EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent]; if(status == EKAuthorizationStatusAuthorized) { [self addEventToCalendar:url]; } else { [self.eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { if (granted) { // Let ensure that our code will be executed from the main queue dispatch_async(dispatch_get_main_queue(), ^{ // The user has granted access to their Calendar; add to calendar [self addEventToCalendar:url]; }); }else { UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Privacy Warning" message:@"Permission was not granted for Calendar" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil]; [alert show]; } }]; } } -(void) addEventToCalendar: (NSURL *)url { MXLCalendarManager* calendarManager = [[MXLCalendarManager alloc] init]; self.defaultCalendar = self.eventStore.defaultCalendarForNewEvents; [calendarManager scanICSFileAtRemoteURL:url withCompletionHandler:^(MXLCalendar *calendar, NSError *error) { MXLCalendarEvent *mxlEvent = calendar.events.firstObject; EKEventEditViewController *addController = [[EKEventEditViewController alloc] init]; EKEvent * event = [EKEvent eventWithEventStore:self.eventStore]; event.location = mxlEvent.eventLocation; event.startDate = mxlEvent.eventStartDate; event.endDate = mxlEvent.eventEndDate; event.title = mxlEvent.eventSummary; event.notes = mxlEvent.eventDescription; addController.event = event; // Set addController event store to the current event store addController.eventStore = self.eventStore; addController.editViewDelegate = self; [self presentViewController:addController animated:YES completion:nil]; }]; } @end 

I also had to slightly modify parts of MXLCalendarManager.m to be prepared for my specific .ics formatting types. For example, my final section of my .ics file looks like this:

 DESCRIPTION;LANGUAGE=en-us:The following details your appointment:\n\n\n 

where MXLCalendarManager searches only:

 DESCRIPTION: (Something). 

I changed the code as such to account for: ln. This also removed all the artificial line breaks, but allowed me to add my own in the summary description:

  // Extract event description [eventScanner scanUpToString:@"DESCRIPTION" intoString:nil]; [eventScanner scanUpToString:@":" intoString:nil]; [eventScanner scanUpToString:@"\nSEQUENCE" intoString:&descriptionString]; if(descriptionString.length > 1) { descriptionString = [descriptionString substringFromIndex:1]; descriptionString = [[[descriptionString stringByReplacingOccurrencesOfString:@"\nSEQUENCE" withString:@""] stringByReplacingOccurrencesOfString:@"\r\n " withString:@""] stringByReplacingOccurrencesOfString:@"\\n" withString:@"\n"]; } 
+2
source

All Articles