iOS的EKEvent商店重建的iCloud日历在一个循环中,不会保存地方。(iOS EKEvent

2019-07-05 05:37发布

我有一个奇怪的问题EKEventStore,iCloud的和当地的日历。 如果iCloud中启用了日历中创建和事件保存到日历,你会期望。 如果icloud是关闭,您尝试保存的事件没有任何反应,但是设备继续在一个循环中每3-5秒钟,直到iCloud中重新打开,然后将所有这些日历洪水到iCloud中的副本创建的iCloud日历。 我使用几乎已此处引用这么多的时间以及在苹果文档确切的代码。 我完全难倒,为什么它不工作,有似乎是EKEventStore很少文档中一般。

//•••••••••••••••••••••••••••••••••••••••••••••••#编译马克 - 保存事件//••••••••••••••••••••••••••••••••••••••••••• ••••

-(void)saveEventWithDate:(NSDate *)startDate endDate:(NSDate *)endDate
{
    AppData *theData = [self theAppData];

    if([self checkIsDeviceVersionHigherThanRequiredVersion:@"6.0"]) {
        [eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) { // iOS 6 Support

            if (granted){
                NSLog(@"Access Granted");
            } else {
                NSLog(@"Access Not Granted");
            }

        }];
    }

    EKEvent *event  = [EKEvent eventWithEventStore:eventStore];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    if ([eventStore calendarWithIdentifier:[defaults objectForKey:@"My Calendar"]] != nil) // Calendar Existed
    {
        event.calendar  = [eventStore calendarWithIdentifier:[defaults objectForKey:@"My Calendar"]];
        NSLog(@"Calendar Existed");

    } else { // Create Calendar

        EKSource *theSource = nil;

        for (EKSource* src in eventStore.sources) {
            if ([src.title isEqualToString:@"iCloud"]) {
                theSource = src;
                break;
            }
            if (src.sourceType == EKSourceTypeLocal && theSource==nil) {
                theSource = src;
                break;
            }
        }

        [self setupCalendarWithSource:theSource withEvent:event];
    }

    NSLog(@"Type of Event:%@",typeOfEvent);

    if ([typeOfEvent isEqualToString:@"Hello"]) {
        event.title     = [NSString stringWithFormat:@"%@ Hello",[theData.hello_info objectForKey:@"customer_name"]];
        event.location  = [NSString stringWithFormat:@"Phone #%@",[theData.hello_info objectForKey:@"customer_phone_number"]];
        event.notes     = [NSString stringWithFormat:@"Hello Issue: %@",[theData.hello_info objectForKey:@"hello_issue"]];
        NSLog(@"Hello");
    }

    event.startDate = startDate;
    event.endDate   = endDate;
    event.allDay    = NO;
    EKAlarm *alarm = [EKAlarm alarmWithRelativeOffset:-1800]; // Half Hour Before
    event.alarms = [NSArray arrayWithObject:alarm];

    [eventStore saveEvent:event span:EKSpanThisEvent error:nil];

    SAFE_PERFORM_WITH_ARG(_delegate, @selector(wasScheduled), nil);
}

-(void)setupCalendarWithSource:(EKSource *)theSource withEvent:(EKEvent *)event {

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];

    EKCalendar *cal;
    cal = [EKCalendar calendarWithEventStore:eventStore];
    cal.title = @"My Appointments";
    cal.source = theSource;
    [eventStore saveCalendar:cal commit:YES error:nil];
    NSLog(@"cal id = %@", cal.calendarIdentifier);
    NSString *calendar_id = cal.calendarIdentifier;
    [defaults setObject:calendar_id forKey:@"My Calendar"];
    event.calendar  = cal;
}

Answer 1:

我不知道为什么你这种行为,但我认为,由于事实,即有残疾的iCloud,系统无法进行查询就可以了,然后排队,一旦你醒来的iCloud决心创建请求(但我假设)。

无论如何,这在我脑海的第一个解决方案是检查的iCloud是主动或不能以这种方式

EKSource *defaultSource = [eventStore defaultCalendarForNewEvents].source;

if (defaultSource.sourceType == EKSourceTypeCalDAV)
    NSLog(@"iCloud Enable");
else
    NSLog(@"iCloud Disable");

做到这一点,你可以适当的事件保存到默认源,然后保持2个日历(当地的一个和云中的一个)彼此同步...

iCloud中的重新激活仍然会提示添加所有本地日历。

在此还看到了第二个答案的iOS设备上访问编程方式创建日历 (这是我的想法;))

我希望我是有帮助的。

编辑:也许是没有必要创建第二个日历...尝试改变从EKSourceTypeCalDAV到EKSourceTypeLocal日历源...不要忘记保存日历提交“YES”

EDIT2:好的刚刚测试过...

替代这样的:

} else { // Create Calendar

    EKSource *theSource = nil;

    for (EKSource* src in eventStore.sources) {
        if ([src.title isEqualToString:@"iCloud"]) {
            theSource = src;
            break;
        }
        if (src.sourceType == EKSourceTypeLocal && theSource==nil) {
            theSource = src;
            break;
        }
    }

    [self setupCalendarWithSource:theSource withEvent:event];
}

有了这个 ...

} else { // Create Calendar

    EKSource *theSource = [eventStore defaultCalendarForNewEvents].source;

    [self setupCalendarWithSource:theSource withEvent:event];
}

这样一来U将建立在正确的源日历(本地用户是否停用的iCloud和CalDAV的其他方式)

然后:

1)当用户选择停用的iCloud应当给iphone日历(而不是删除),所以u有本地源云日历

2)当用户选择激活的iCloud将合并了本地日历与云和有ü去!

我希望这会帮助



Answer 2:

如果你想有一个防弹的方式找到的iCloud日历和恢复到本地日历如果iCloud中被禁用,使用下面的代码。 我已经包括了一些意见可能帮助:

for (EKSource *source in eventStore.sources) {  //Check for iCloud
    if (source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"]) {

        NSLog(@"Found iCloud Service.");  //Found iCloud

        if([source calendarsForEntityType:EKEntityTypeEvent].count>0){     //Check to see if Calendar is enabled on iCloud

            NSLog(@"iCloud Calendar is Enabled."); //Calendar is Enabled

            if([self saveEventCalendarWithSource:source]){
                return YES;
            }

        }else{

            NSLog(@"iCloud Calendar is Disabled."); //Calendar is Disabled

        }
    }
}


//If we are here it means that we did not find iCloud Source with iCloud Name. Now trying any CalDAV type to see if we can find it

for (EKSource *source in self.reminderStore.sources) {  //Check for iCloud
    if (source.sourceType == EKSourceTypeCalDAV) {

        [self logData:@"Trying to save calendar in EKSourceTypeCalDAV Service."];

        if([self saveEventCalendarWithSource:source]){
            return YES;
        }

    }
}

//If we are here it means that we did not find iCloud and that means iCloud is not turned on. Use Local service now.

for (EKSource *source in self.reminderStore.sources) {  //Look for Local Source
    if (source.sourceType == EKSourceTypeLocal){  //Found Local Source
        NSLog(@"Found Local Source.");

        if([self saveEventCalendarWithSource:source]){
            return YES;
        }

    }
}

下面的代码保存日历:

- (Boolean) saveEventCalendarWithSource:(EKSource *)source{

EKCalendar *Calendar = nil;

MyCalendar = [EKCalendar calendarForEntityType:EKEntityTypeEvent eventStore:eventStore];

MyCalendar.title = @"XXX";
MyCalendar.CGColor = [UIColor blueColor].CGColor;

MyCalendar.source = source;

NSError *err;
if([eventStore saveCalendar:MyCalendar commit:YES error:&err]){

    if(MyCalendar.calendarIdentifier == nil){

        NSLog(@"Could not save Calendar: %@",err);

        return FALSE;
    }

    NSLog(@"Calendar Created. Here's the identifier %@",[MyCalendar calendarIdentifier]);

    return TRUE;
}

NSLog(@"Could not create calendar! Reason:%@",err.description);

return FALSE;

}



Answer 3:

您的文章是一个很大的帮助,我挣扎威特完全相同的漏洞。 谢谢 !

我只是做了小的修改,如使用defaultCalendarForNewEvents'源的解决方案在任何情况下不工作:某些源不会让你在其中创建新的日历。

我查一下我的iCloud源的日历数。 如果计数为零,则日历同步是关闭的,而我走的地方来源:

EKSource* localSource = nil;
EKSource* iCloudSource = nil;
for (EKSource* source in _eventStore.sources){
    if (source.sourceType == EKSourceTypeLocal){
        localSource = source;
    }else if(source.sourceType == EKSourceTypeCalDAV && [source.title isEqualToString:@"iCloud"]){
        iCloudSource = source;
    }
}

if (iCloudSource && [iCloudSource.calendars count] != 0) {
    calendar.source = iCloudSource;
}else{
    calendar.source = localSource;
}


文章来源: iOS EKEvent Store recreating iCloud calendars in a loop, won't save local.