我遇到了一个问题,即我创建了我的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);
}
}
提前谢谢!
答案 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;
}
}