iOS: Исходники EKEventStore / defaultCalendarForNewEvents / calendarsForEntityType все ничего не возвращают ПОСЛЕ авторизации

У меня есть приложение, я пытаюсь помочь выйти за дверь. Этот код изначально был написан для iOS5 другой командой. Я добавил вызов requestAccessToEntityType:completion:, который выполняется успешно. Однако после предоставления доступа я не получаю никаких источников / defaultCalendar или календарей на основе объекта. И я не могу создать новый календарь.

При вызове defaultCalendarForNewEvents я получаю эту ошибку

Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)" и результат нулевой.

Если я выхожу из viewController, пытаясь сделать это, и возвращаюсь, все работает нормально. Если после получения предупреждения об отсутствии источника я продолжаю попытки (без резервного копирования viewController), это неоднократно терпит неудачу.

Хочу подчеркнуть, что авторизационный звонок работает (у пользователя запрашивают доступ к календарям и он его дает, а потом звонит для подтверждения прохождения авторизации). Все другие похожие вопросы, которые я нашел, имеют это в качестве решения - убедитесь, что вы запрашиваетеAccessToEntityType

[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
    if (granted)
        {
       //[self performSelectorOnMainThread:@selector(doScheduleActivity:) withObject:activity waitUntilDone:YES];
           dispatch_async(dispatch_get_main_queue(), ^{
                [self doScheduleActivity:activity];
                });
           }
       else
       { // probably should force the main thread
         dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView *av = [[UIAlertView alloc] initWithTitle:@"Calendar Access Required" message:@"In order to schedule activities, APP needs access to your Calendar.  You can change this in your device Settings." delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
            [av show];
            });
         }

}] ;

granted возвращается true, и [self doScheduleActivity: вызывается. Следующий код представляет собой функцию, вызываемую в самом начале этой подпрограммы, где и происходят сбои.

EKCalendar *saCalendar;
EKSource *source;
NSError *error;
UIAlertView *alert;

LogDebug(@"eventStore defaultCalendar %@", [eventStore defaultCalendarForNewEvents]);

// validate access to calendar prior to segueing
if ([EKEventStore respondsToSelector:@selector(authorizationStatusForEntityType:)])
{
    switch([EKEventStore authorizationStatusForEntityType:EKEntityTypeEvent])
    {
        case EKAuthorizationStatusAuthorized:
            break;
        case EKAuthorizationStatusNotDetermined:
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:SA_ALERT_CAPTION_CALENDAR_ACCESS_NOT_DETERMINED message:SA_ALERT_BODY_CALENDAR_ACCESS_NOT_DETERMINED delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                    [alert show];
                    });
                return false;
                }
        case EKAuthorizationStatusDenied:
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:SA_ALERT_CAPTION_CALENDAR_ACCESS_DENIED message:SA_ALERT_BODY_CALENDAR_ACCESS_DENIED delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                    [alert show];
                    });
                return false;
                }
        case EKAuthorizationStatusRestricted:
            {
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIAlertView *alert = [[UIAlertView alloc] initWithTitle:SA_ALERT_CAPTION_CALENDAR_ACCESS_RESTRICTED message:SA_ALERT_BODY_CALENDAR_ACCESS_RESTRICTED delegate:nil cancelButtonTitle:@"Ok" otherButtonTitles:nil];
                    [alert show];
                    });
                return false;
                }
        default:
            break;
    }
}

// search for application specifc calendar..
saCalendar = nil;
for(EKCalendar *calendar in [eventStore calendarsForEntityType:EKEntityTypeEvent])
{
    if([calendar.title isEqualToString:SA_ACTIVITIES_CALENDAR_TITLE])
    {
        saCalendar = calendar;
        break;
    }
}
// ..and create from scratch if nonexistent
if(nil == saCalendar)
{
    // find local source to hook up new calendar to
    for(source in [eventStore sources])
    {
        if(source.sourceType == EKSourceTypeLocal)
        {
            break;
        }
    }

    // if could not find local source type, something is wrong
    if( source == nil || source.sourceType != EKSourceTypeLocal)
    {
        alert = [[UIAlertView alloc] initWithTitle:SA_ALERT_CAPTION_CALENDAR_ERROR_NO_SOURCE message:SA_ALERT_BODY_CALENDAR_ERROR delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
        [alert show];
        return false;
    }

    // create calendar for applcation, name it, color it and assign source
    saCalendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:eventStore];
    [saCalendar setSource:source];
    [saCalendar setTitle:SA_ACTIVITIES_CALENDAR_TITLE];
    [saCalendar setCGColor:[[UIColor yellowColor] CGColor]];

    // create immediately
    error = nil; 
    if(![eventStore saveCalendar:saCalendar commit:true error:&error])
    {
        dispatch_async(dispatch_get_main_queue(), ^{
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:SA_ALERT_CAPTION_CALENDAR_ERROR_CANT_SAVE message:SA_ALERT_BODY_CALENDAR_ERROR delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil];
            [alert show];
            });
        return false;
    }
}

return true;

Все возвращается nil, хотя было авторизовано, и проверка в [EKEventStore authorizationStatusForEntity:EKEntityType возвращает EKAuthorizationStatusAuthorized

После того, как я получу здесь ошибку, если я выйду из этого контроллера представления и вернусь, это сработает. Это происходит только в первый раз, когда система запрашивает у пользователя доступ к календарю, и он отвечает «ОК».

Спасибо за любое понимание. Я прошел через отладчик, а также выполнял отладку типа printf, чтобы избежать каких-либо проблем с синхронизацией и т. Д., И не вижу ничего, что противоречило бы событиям, которые я искал на сайте Apple.

Мое целевое устройство 6.1.3 iPhone 5


person chadbag    schedule 31.07.2013    source источник


Ответы (2)


Хорошо, оказалось, что в viewDidLoad была небольшая строка кода, которая была перед кодом [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error и которая пыталась получить доступ к eventStore. Это было лишним и не должно было происходить, и я этого не заметил. После того, как я удалил этот код, материал теперь работает, поэтому он возвращается к необходимости авторизации, поскольку даже после авторизации хранилище событий уже было «плохим» из-за этого предыдущего доступа.

person chadbag    schedule 31.07.2013

Проблема также может быть решена путем повторного создания экземпляра EKEventStore в обратном вызове после предоставления доступа.

person zeroimpl    schedule 03.01.2015
comment
Этот, кажется, решает проблему. Но не смог найти, в чем была проблема. Есть идеи? - person Vipin Johney; 03.03.2015
comment
Я думаю, что это просто ошибка iOS, когда вы пытаетесь получить доступ к хранилищу событий до авторизации. - person zeroimpl; 12.03.2015