6

我有一个应用程序,我正试图帮助走出门。这段代码最初是由另一个团队使用 iOS5 编写的。我添加了成功运行的 requestAccessToEntityType:completion: 调用。但是,在被授予访问权限后,我没有得到任何来源/defaultCalendar 或基于实体的日历。而且我无法创建新日历。

调用 defaultCalendarForNewEvents 时出现此错误

Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)" 结果为零。

如果我退出 viewController 尝试执行此操作并返回,一切正常。如果在收到关于没有来源的警报后,我继续尝试(没有退出 viewController),它会反复失败。

我想强调,授权调用有效(用户被要求访问日历并提供它,然后调用以确认授权通过)。我发现的所有其他类似的问题都作为解决方案 - 确保您 requestAccessToEntityType

[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

在我在这里遇到故障后,如果我退出这个视图控制器并重新进入,它就可以工作。这只发生在系统第一次要求用户访问日历并且他们回复 OK 时。

感谢您的任何见解。我一直在逐步调试调试器,并进行 printf 类型调试以避免任何时间问题等,并且没有看到与我在 Apple 网站上查找的事件内容相反的内容。

我的目标设备是 6.1.3 iPhone 5

4

2 回答 2

9

好的,事实证明 viewDidLoad 中有一小行代码在[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error代码之前并试图访问 eventStore。这是多余的,不需要发生,我没有注意到。一旦我删除了这段代码,这些东西现在就可以工作了,所以它确实需要授权,因为即使在授权之后,由于之前的访问,eventStore 已经“坏”了。

于 2013-07-31T18:31:38.107 回答
7

一旦授予访问权限,也可以通过在回调中重新创建 EKEventStore 实例来解决该问题。

于 2015-01-03T01:16:38.823 回答