检测EKStore是否允许创建日历

时间:2014-08-06 14:38:54

标签: ios eventkit caldav

我正在开发一个需要将数据发布到用户的calDAV日历(iCloud或其他)的应用程序。为此,我需要检测该源是否允许创建日历和提醒。

EKSource在检测任何内容方面没有提供太多,除了为您提供源类型(本地,calDAV,Exchange ......)

我想到的唯一方法是检测这是否可行是实际上尝试编写一个新的日历并查看任何错误消息,如下所示:

 -(BOOL)ekSourceWritesToEvents:(EKSource *)ekSource {
    BOOL writesToEvents = NO;
    //Try to write a calendar to it if it fails, return NO
    //If you succeed, return YES, since this is uncommitted, no damage done
    NSError *error = nil;
    EKCalendar *testCalendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:self.eventStore];
    testCalendar.title = @"TestCalendar";
    testCalendar.source =  ekSource;

    BOOL result = [self.eventStore saveCalendar:testCalendar commit:NO error:&error];
    if (result) {
        NSLog(@"This Source can create calendars: %@",ekSource.title);

        //Now check if one can create an event
        EKEvent *newEvent = [EKEvent eventWithEventStore:self.eventStore];
        newEvent.title = @"TestEvent";
        newEvent.startDate = [NSDate date];
        newEvent.endDate = [NSDate date];
        newEvent.calendar = testCalendar;

        NSError *eventCreateError = nil;
        [self.eventStore saveEvent:newEvent span:EKSpanThisEvent commit:NO error:&eventCreateError];

        if (eventCreateError) {
            NSLog(@"Cannot Create EKEvent in test Calendar %@",eventCreateError.localizedDescription);
            writesToEvents = NO;
        } else {
            writesToEvents = YES;
            //Delete it even if uncommitted or it seems to get commited at some point
            NSError *eventDeleteError = nil;
            [self.eventStore removeEvent:newEvent span:EKSpanThisEvent commit:YES error:&eventDeleteError];
            if (eventDeleteError) {
                NSLog(@"Error removing event: %@",eventDeleteError.localizedDescription);
            }

        }
        NSError *calendarDeleteError = nil;
        [self.eventStore removeCalendar:testCalendar commit:YES error:&calendarDeleteError];
        if (calendarDeleteError) {
            NSLog(@"Error removing test calendar: %@",calendarDeleteError.localizedDescription);
        }

    } else {
        NSLog(@"Cannot Save Calendar: %@.", error);
    }
    return writesToEvents;
}

我发现这是一种笨重的做事方式......难道没有办法正确地检测到这种情况吗?我希望用户在选择目标源之前知道会发生什么,这就是为什么我要在实际尝试之前执行此操作。

谢谢!

更新:似乎检查日历创建是不够的。你还必须测试创建的日历允许写...我正在调查。为什么一个人创建一个日历而不允许它写作是超出我的...

更新2:似乎即使我们不提交,测试日历也会以某种方式创建。所以我添加了代码来删除测试事件和日历。

更新3:更多问题...检查日历创建功能并非全部...某些服务(Google)允许您在日历中创建活动,但不能在日历中创建活动。您必须使用Google网站或其API创建日历。最重要的是,当您尝试创建EKEvent时,Exchange服务器似乎存在错误,它实际上会给您一个错误,即日历无法创建提醒。怪异。

3 个答案:

答案 0 :(得分:0)

如果您使用的是事件编辑视图控制器,则可以使用它来获取日历。

-(EKCalendar *)eventEditViewControllerDefaultCalendarForNewEvents:(EKEventEditViewController *)controller {

    EKCalendar *defaultCalendar = [[eventStore defaultCalendarForNewEvents] init];

    return defaultCalendar;
}

答案 1 :(得分:0)

我在寻找解决同样问题时偶然发现了这一点。我正在考虑尝试测试日历创建,所以我和你在一起。而不是测试事件创建,为什么不检查新日历以查看它是否允许使用allowContentModifications属性修改事件?

答案 2 :(得分:0)

要创建EKCalender,EKEvent,您需要获得创建EKSource(iCloud,Birthday,Google帐户)的权限。 如果您打印或转储EKSource对象,则可以看到此数据。

EKSource <0x3734900>, displayOrder:-1, isDelegate:0, isEnabledForEvents:1, isEnabledForReminders:1, ownerAddresses:{(
)}, supportsAttendeeComments:0, supportsDropBoxAttachments:0, supportsEmailValidation:0, supportsEventCalendarCreation:0, supportsFreebusy:0, supportsJunkReporting:0, supportsLikenessPropagation:0, supportsPhoneNumbers:0, supportsPrivateEvents:0, supportsManagedAttachments:0, supportsSharingScheduling:0, supportsTaskCalendarCreation:0, typeString:Birthday, supportsUnbind:1, isWritable:1, sourceIdentifier:Birthday
    title               : Other

我不知道为什么Apple文档没有描述这些属性,但是如果某些EKSource(iCloud,Birthday,Google帐户)允许创建或编辑事件日历,则将“ supportsEventCalendarCreation”设置为1。如果将其设置为0,则失败添加EKCalendar和EKEvent。 (允许创建提醒的属性可能是“ supportsTaskCalendarCreation”)

您需要使用此方法来访问属性。 https://developer.apple.com/documentation/objectivec/nsobject/1412591-valueforkey? language=objc

下面是快速代码。

func canWritesEventsToEKSource(ekSource:EKSource) -> Bool {
    if let value = ekSource.value(forKey: "supportsEventCalendarCreation") as? Int,
        value == 1 {
        return true
    } else {
        return false
    }
}

func canWritesRemindersToEKSource(ekSource:EKSource) -> Bool {
    if let value = ekSource.value(forKey: "supportsTaskCalendarCreation") as? Int,
        value == 1 {
        return true
    } else {
        return false
    }
}