如何在iOS 6上创build和保存EKCalendar

我有一个问题,我创build我的EKCalendar,一切看起来不错,但是当我去列出我的日历,它不显示。 我也去我的日历应用程序检查我的日历列表,但它是不存在的。 有什么想法吗?

这是我的button代码来创build我的日历:

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

这里是我的button代码来列出日历,但我的新日历从来没有包括在内!

 - (IBAction)two:(id)sender { NSArray *calendars = [eventStore calendarsForEntityType:EKEntityTypeEvent]; for (EKCalendar* cal in calendars){ NSLog(@"%@",cal.title); } } 

先谢谢你!

我find了解决scheme。 问题是,当开启iCloud日历时,它会从日历应用程序中隐藏本地创build的日历。 为了绕过这个问题,解决scheme是添加一个新的日历到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; } } } 

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

对于EKEventStore文档:

 + (EKAuthorizationStatus)authorizationStatusForEntityType:(EKEntityType)entityType - (void)requestAccessToEntityType:(EKEntityType)entityType completion:(EKEventStoreRequestAccessCompletionHandler)completion 

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

我也有这个问题。 我的解决scheme几乎和其他答案一样,但我用另一种方法来获取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等),则无法将日历添加到其源。

在这种罕见的情况下,我使用全面search:

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

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

这是我可以find的最可靠的解决scheme,而不用硬编码任何假设:

  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) 

我有这个相同的问题。 我做了六点build议,并有应用程序要求许可。 这解决了一部分,但日历并没有显示出来,但正在创build根据NSLogs。 我的手机上有一个Exchange日历(我没有iCloud),不得不closures它。 一旦删除,它显示为本地日历。 当我回去重新添加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); } } 

解决schemeMassimo Oliviero没有为我工作。 我遇到过同样的问题。 我在调用requestAccessToEntityType之后创build了Calendar。
什么对我来说是获得许可后我重新初始化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]); }} 

我不会推荐最好的答案,因为它依赖于检查“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; } }