15

我在创建 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);
}

}

先感谢您!

4

7 回答 7

36

我找到了解决方案。问题是当 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;
            }
        }
    }
于 2013-04-12T20:45:49.073 回答
7

我也有这个问题。我的解决方案几乎与其他答案一样,但我使用另一种方式来获取 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
    }
}
于 2015-06-30T15:46:45.433 回答
4

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

对于EKEventStore文档:

+ (EKAuthorizationStatus)authorizationStatusForEntityType:(EKEntityType)entityType

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

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

于 2013-03-29T16:30:15.963 回答
3

本地商店可能不支持事件。如果启用了 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)
于 2015-10-13T23:45:08.060 回答
0

我有同样的问题。我按照 sixcent 的建议做了,并让应用程序请求许可。这解决了一部分,但日历仍然没有显示,而是根据 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);
}

}
于 2013-07-05T20:43:24.463 回答
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]);
    }
}];

在日历管理器中

- (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]);
}}
于 2017-02-06T14:37:46.143 回答
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;
    }
}
于 2017-10-25T09:39:42.633 回答