UIDocumentInteractionController Calendar Access

*爱你&永不变心* 提交于 2019-12-05 09:14:43

问题


I have an ics (Calendar) file that I'm opening with a UIDocumentInteractionController, using presentOptionsMenuFromRect:. When this runs, the "Open In" menu looks like this.

As you can see, no "Add to Calendar" option. Here's what gets me: I'm using the same exact code for a .vcf (contact card) file, and it works as expected with the "Open In Contacts" option available.

Am I missing some sort of permission in my Info.plist for calendar access? Why can't UIDocumentInteractionController handle the .ics file type correctly, but .vcf works just fine? Those two file types are very similar. From the options menu, if I mail the ics file to myself and open it from the mail app, it reads it just fine, and I can add the events to my calendar, so I know the data is valid. I've searched high and low for a solution, and nobody seems to know why Calendar access isn't working. Some questions I've come across that remain unanswered:

Unable to Add ics file to Calendar

How can I have UIDocumentInteractionController show Calendar as an option for opening a .ics file?

If Apple is doing this deliberately, the only reason I can think of is because they'd rather developers use EventKit to add events to Calendar. If true, that solution is rather frustrating. Any insight on this problem would be much appreciated.


回答1:


I ended up downloading the .ics file via (https://github.com/KiranPanesar/MXLCalendarManager). I was then able to use EventKit to parse the downloaded .ics file into an EKEvent and open it via EKEventEditViewController (https://developer.apple.com/library/prerelease/ios/samplecode/SimpleEKDemo/Listings/Classes_RootViewController_m.html). A little round about but seemed to work. Here's how I setup 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's 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's 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 ready for my specific types of .ics formatting. For example, my summary section of my .ics file looks like:

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

where as MXLCalendarManager is only looking for:

DESCRIPTION: (Something). 

I modified the code as such to account for the ;ln. This also removed all the artificial line breaks but allowed me 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"];
    }


来源:https://stackoverflow.com/questions/27927665/uidocumentinteractioncontroller-calendar-access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!