Определение того, разрешает ли EKStore создание календарей

Я работаю над приложением, которому необходимо публиковать данные в календаре пользователя 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. Вдобавок ко всему, кажется, что есть ошибка с серверами Exchange, когда вы пытаетесь создать EKEvent, это фактически дает вам ошибку, что календарь не может создавать напоминания. Странный.


person Renaud Boisjoly    schedule 06.08.2014    source источник


Ответы (3)


Чтобы создать EKCalender, EKEvent, вам необходимо разрешение на создание EKSource (iCloud, Birthday, Google Account). если вы печатаете или выгружаете объект 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. и ЭКЕвент. (Свойство, которое позволяет создавать напоминания, может быть «supportsTaskCalendarCreation»)

Вам нужно использовать этот метод для доступа к свойству. https://developer.apple.com/documentation/objectivec/nsobject/1412591-valueforkey?%20language=objc

Код Swift ниже.

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
    }
}
person kj13    schedule 02.01.2020

Если вы используете контроллер представления редактирования событий, вы можете просто использовать его для получения календаря.

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

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

    return defaultCalendar;
}
person Tom Testicool    schedule 06.08.2014
comment
Что ж, я не использовал контроллер Event Edit View, но в основном вопрос был о создании календаря в учетной записи, а не о создании события или напоминания, на что, похоже, указывает ваш ответ, но спасибо. - person Renaud Boisjoly; 28.01.2015
comment
По крайней мере, в iOS9 даже источник событий календаря по умолчанию не гарантирует, что он разрешает создание календаря. - person leogdion; 17.09.2015

Я наткнулся на это, пытаясь решить ту же проблему. Я думал о том, чтобы попробовать создать календарь, так что я с вами в этой части. Однако вместо того, чтобы тестировать создание событий, почему бы просто не проверить новый календарь, чтобы увидеть, позволяет ли он изменять события с помощью своего свойства allowContentModifications?

person vichudson1    schedule 25.01.2015
comment
Да, тестирование создания событий/напоминаний в этом случае подходит, вопрос касается создания календаря для начала. Невозможно проверить создание календаря, кроме как попытаться создать его и получить ошибку или нет, а в случае успеха удалить тестовый календарь или использовать его. В моем случае я хотел получить список возможных целей для размещения календаря, поэтому я не хотел пытаться и потерпеть неудачу или позволить пользователю выбрать тот, который не был доступен для записи, поэтому мне пришлось сделать это таким образом. - person Renaud Boisjoly; 28.01.2015
comment
Да полностью. Я понял. Я просто имел в виду, что тестовые события на самом деле не нужны. Очень жаль, что нет простого вызова API для решения этой проблемы. - person vichudson1; 28.01.2015