How to create and save EKCalendar on ios 6

2020-01-30 08:15发布

I'm having an issue where I create my EKCalendar and everything looks good but then when I go to list my calendars, it doesn't show up. I also go to check my calendar list in my calendar app but it is non existant. Any thoughts?

Here is my button code to create my calendar:

- (IBAction)one:(id)sender {
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
}
NSLog(@"cal id = %@", calendar.calendarIdentifier);
}

And here is my button code to list the calendar, but my new calendar is never included!

- (IBAction)two:(id)sender {

NSArray *calendars = [eventStore calendarsForEntityType:EKEntityTypeEvent];

for (EKCalendar* cal in calendars){
    NSLog(@"%@",cal.title);
}

}

Thank you in advance!

7条回答
SAY GOODBYE
2楼-- · 2020-01-30 08:25

The solution Massimo Oliviero did not work for me. I had the same issue. I was creating Calendar after calling requestAccessToEntityType.
What worked for me is after getting the permission I reinitialised the EventStore object. It was like the permissions were never upadted.

[[CalendarManager sharedManager].eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    if (granted && error == nil) {
        // Store the returned granted value.
        [CalendarManager sharedManager].eventsAccessGranted = granted;
        if (![CalendarManager sharedManager].calendarCreated) {
            [[CalendarManager sharedManager] createCalendar];
        }
    }
    else{
        // In case of error, just log its description to the debugger.
        DebugLog(@"%@", [error localizedDescription]);
    }
}];

In CalendarManager

- (void)createCalendar {

_eventStore = nil;
_eventStore = [EKEventStore new];

// Create a new calendar.
EKCalendar *calendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent
                                              eventStore:self.eventStore];

// Set the calendar title.
calendar.title = CALENDAR_NAME;

EKSource *theSource;

// First: Check if the user has an iCloud source set-up.
for (EKSource *source in self.eventStore.sources) {
    if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"]) {
        theSource = source;
        break;
    }
}

// Second: If no iCloud source is set-up / utilised, then fall back and use the local source.
if (theSource == nil) {
    for (EKSource *source in self.eventStore.sources) {
        if (source.sourceType == EKSourceTypeLocal)  {
            theSource = source;
            break;
        }
    }
}

calendar.source = theSource;

// Save and commit the calendar.
NSError *error;
[_eventStore saveCalendar:calendar commit:YES error:&error];

// If no error occurs then turn the editing mode off, store the new calendar identifier and reload the calendars.
if (error == nil) {
    self.calendarCreated = YES;
}
else {
    self.calendarCreated = NO;
    // Display the error description to the debugger.
    DebugLog(@"%@", [error localizedDescription]);
}}
查看更多
闹够了就滚
3楼-- · 2020-01-30 08:32

Have you tried checking authorization setting first to make sure the user has given permission to access the store?

For EKEventStore documentation:

+ (EKAuthorizationStatus)authorizationStatusForEntityType:(EKEntityType)entityType

- (void)requestAccessToEntityType:(EKEntityType)entityType completion:(EKEventStoreRequestAccessCompletionHandler)completion

Important: If your app has never requested access before, you must request access to events or reminders before attempting to fetch or create them. If you request data before prompting the user for access with this method, you'll need to reset the event store with the reset method in order to start receiving data once the user grants access.

查看更多
不美不萌又怎样
4楼-- · 2020-01-30 08:32

The local store may not support events. This is reproducible if iCloud is enabled.

This is the most reliable solution I could find, without hard-coding any assumptions:

    let calendar = EKCalendar(forEntityType: .Event, eventStore: eventStore)

    if eventStore.sources.count == 0 { // reproducible after Reset Content and Settings
        calendar.source = EKSource()
    }
    else {
        calendar.source = eventStore.defaultCalendarForNewEvents.source
    }

    eventStore.saveCalendar(calendar, commit: true)
查看更多
对你真心纯属浪费
5楼-- · 2020-01-30 08:33

I found a solution. The problem is that when iCloud calendars switched on, it hides the locally created ones from the calendar app. To bypass this problem the solution is to add a new calendar to iCloud source:

    for (EKSource *source in self.eventStore.sources)
    {
        if (source.sourceType == EKSourceTypeCalDAV && 
           [source.title isEqualToString:@"iCloud"]) //Couldn't find better way, if there is, then tell me too. :)
        {
            localSource = source;
            break;
        }
    }

    if (localSource == nil)
    {
        for (EKSource *source in self.eventStore.sources)
        {
            if (source.sourceType == EKSourceTypeLocal)
            {
                localSource = source;
                break;
            }
        }
    }
查看更多
Deceive 欺骗
6楼-- · 2020-01-30 08:35

I had this problem too. My solution is nearly like other answers, but I use another way to get the instance of EKSource.

As written in documentation:

/* 
 * Returns the calendar that events should be added to by default, 
 * as set in the Settings application.
 */
@property EKCalendar *defaultCalendarForNewEvents; 

So, I use this code to get the proper EKSource:

EKSource *theSource = [self.eventStore defaultCalendarForNewEvents].source;

BUT if you use another calendar like Gmail (or Yahoo etc.), you can't add your calendar to its source.

In this rare case I use a full search:

EKSource *theSource;
for (EKSource *source in eventStore.sources) {
    if (source.sourceType == EKSourceTypeSubscribed) {
        theSource = source;
        break; // stop when source is found
    }
}
查看更多
时光不老,我们不散
7楼-- · 2020-01-30 08:37

I had this same problem. I did as sixthcent suggested and had the app ask for permission. That solved one part but the calendar didn't show up still but was being created according to the NSLogs. I had an Exchange calendar (I didn't have iCloud) on my phone and had to turn it off. Once that was deleted it showed up as a Local calendar. When I went back to re-add Exchange it asked if I wanted to keep both and now both calendars are showing up. Here is my code below.

#import "ViewController.h"
#import <EventKit/EventKit.h>
#import <EventKitUI/EventKitUI.h>

@interface ViewController ()
@end

@implementation ViewController

- (void)viewDidLoad
{
[super viewDidLoad];  

EKEventStore *store = [[EKEventStore alloc] init];
EKSource *localSource = nil;
for (EKSource *source in store.sources)
{
    if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"])
    {
        localSource = source;
        break;
    }
}
if (localSource == nil)
{        
    for (EKSource *source in store.sources) {
        if (source.sourceType == EKSourceTypeLocal)
        {
            localSource = source;
            break;
        }
    }
}

EKEventStore *es = [[EKEventStore alloc] init];
[es requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    /* This code will run when uses has made his/her choice */

    if (error)
    {
        // display error message here
    }
    else if (!granted)
    {
        // display access denied error message here
    }
    else
    {
        // access granted          
    }


}];

//NSString *identifier; //Use to create for the first time and store somewhere
NSString *identifier = @"704A1304-5213-4AB3-9C7B-F6B59E3454BB"; //Stored version

//Create the calendar
EKCalendar *cal;
if (identifier == nil)
{
    cal = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:store];

    cal.title = @"Demo1 Calendar";
    cal.source = localSource;
    [store saveCalendar:cal commit:YES error:nil];
    NSLog(@"cal id = %@", cal.calendarIdentifier);

} else {
    //Calendar already exists!
    cal = [store calendarWithIdentifier:identifier];
    NSLog(@"cal id = %@", cal.calendarIdentifier);
}

//calendar properties
NSLog(@"%@", cal);

//Add Event to Calendar
NSLog(@"Adding event!");
EKEventStore *eventStore = [[EKEventStore alloc] init];

EKEvent *event  = [EKEvent eventWithEventStore:eventStore];
event.title     = @"Event3";

NSDate *startDate = [NSDate date];
event.calendar = cal;
event.startDate = startDate;
event.endDate = [startDate dateByAddingTimeInterval:3600];

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: %@.", error);
}

}
查看更多
登录 后发表回答