如何在ios 6上创建和保存EKCalendar

时间:2013-03-29 16:09:54

标签: ios objective-c ios6 calendar

我遇到了一个问题,即我创建了我的EKCalendar并且一切看起来都不错,但是当我去列出我的日历时,它并没有显示出来。我也去我的日历应用程序查看我的日历列表,但它不存在。有什么想法吗?

以下是我创建日历的按钮代码:

- (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);
}

这是我的按钮代码列出日历,但我的新日历从未包含在内!

- (IBAction)two:(id)sender {

NSArray *calendars = [eventStore calendarsForEntityType:EKEntityTypeEvent];

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

}

提前谢谢!

7 个答案:

答案 0 :(得分:33)

我找到了解决方案。问题是,当iCloud日历打开时,它会从日历应用程序中隐藏本地创建的日历。要绕过此问题,解决方案是向iCloud源添加新日历:

    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;
            }
        }
    }

答案 1 :(得分:6)

我也有这个问题。我的解决方案几乎与其他答案一样,但我使用另一种方式来获取EKSource的实例。

如文档中所述:

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

所以,我使用这段代码来获得正确的EKSource:

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

如果您使用其他日历,例如 Gmail (或Yahoo等),则无法将日历添加到其来源。

在极少数情况下,我使用完整搜索:

EKSource *theSource;
for (EKSource *source in eventStore.sources) {
    if (source.sourceType == EKSourceTypeSubscribed) {
        theSource = source;
        break; // stop when source is found
    }
}

答案 2 :(得分:4)

您是否尝试首先检查授权设置以确保用户已授予访问商店的权限?

对于EKEventStore文档:

+ (EKAuthorizationStatus)authorizationStatusForEntityType:(EKEntityType)entityType

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

重要:如果您的应用之前从未请求过访问权限,则必须在尝试获取或创建事件或提醒之前请求访问事件或提醒。如果在提示用户使用此方法进行访问之前请求数据,则需要使用reset方法重置事件存储,以便在用户授予访问权限后开始接收数据。

答案 3 :(得分:2)

本地商店可能不支持活动。如果启用了iCloud,这是可重现的。

这是我能找到的最可靠的解决方案,没有对任何假设进行硬编码:

    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)

答案 4 :(得分:0)

我有同样的问题。我做了第六次建议并让应用程序请求许可。这解决了一个部分,但日历没有显示,但根据NSLogs创建。我的手机上有一个Exchange日历(我没有iCloud),不得不将其关闭。删除后,它会显示为本地日历。当我回去重新添加Exchange时,它询问我是否要保留两者,现在两个日历都会出现。以下是我的代码。

#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);
}

}

答案 5 :(得分:0)

解决方案Massimo Oliviero不适合我。我遇到过同样的问题。我在致电requestAccessToEntityType后创建了日历。
对我有用的是获得权限后重新初始化EventStore对象。这就像权限从未被提升过。

[[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]);
    }
}];

在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]);
}}

答案 6 :(得分:0)

我不推荐最佳答案,因为它依赖于检查“iCloud”作为名称,这可以由用户更改。如果你只是想确保日历得到保存而你不一定关心它得到什么来源,你可以这样做:

EKCalendar *calendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:eventStore];
calendar.title = @"Calendar name";

NSError *calendarError = nil;
for (EKSource *source in eventStore.sources) {
    // We know the birthday source is read-only
    if (source.sourceType == EKSourceTypeBirthdays) {
        continue;
    }

    calendar.source = source;
    [eventStore saveCalendar:calendar commit:YES error:&calendarError];

    // If saving succeeded, we break, otherwise we try a new source
    if (!calendarError) {
        break;
    }
}