iOS EKEvent Store 循环重新创建 iCloud 日历,不会保存在本地。

标签 ios ekeventkit ekeventstore

我遇到了 EKEventStore、iCloud 和本地日历的奇怪问题。如果启用了 iCloud,则会创建日历并将事件保存到您期望的日历中。如果 iCloud 已关闭并且您尝试保存事件,则没有任何反应,但是设备会继续每 3-5 秒循环创建 iCloud 日历,直到 iCloud 重新打开,然后所有这些日历都会作为副本涌入 iCloud。我使用的代码几乎与此处以及 Apples Docs 中多次引用的代码完全相同。我完全不知道为什么它不起作用,而且一般来说,关于 EKEventStore 的文档似乎很少。

//•••••••••••••••••••••••••••••••••••••••••••••••••••••••• •• #pragma mark——保存事件 //•••••••••••••••••••••••••••••••••••••••••••••••••

-(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;
}

最佳答案

我不确定你为什么会出现这种行为,但我认为由于禁用了 iCloud,系统无法对其进行查询,然后排队创建请求,这些创建请求在你唤醒 iCloud 后得到解决(但我假设)。

无论如何,我想到的第一个解决方案是通过这种方式检查 iCloud 是否处于事件状态

EKSource *defaultSource = [eventStore defaultCalendarForNewEvents].source;

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

完成后,您可以将事件正确保存到默认源,然后保持 2 个日历(本地日历和云端日历)彼此同步 ...

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

另请参阅此处的第二个答案 Accessing programmatically created calendar on iOS device (这就是我的想法;))

希望对您有所帮助。

编辑:也许没有必要创建第二个日历...尝试将日历的来源从 EKSourceTypeCalDAV 更改为 EKSourceTypeLocal ...不要忘记使用提交"is"保存日历

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];
}

这样您将在正确的来源中创建日历(如果用户停用 iCloud 和 CalDAV,则为本地)

然后:

1) 当用户选择停用 iCloud 时,应该将日历保留在 iPhone 上(而不是删除),这样您就可以在本地源中拥有云日历

2) 当用户选择激活 iCloud 时,会将他的本地日历与云合并,然后就可以了!!

希望对你有帮助

关于iOS EKEvent Store 循环重新创建 iCloud 日历,不会保存在本地。,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13869118/

相关文章:

iphone - 为 EKEventEditViewController 设置背景颜色/图像

iphone - 将参与者添加到 iOS 中的事件

ios - 如何向 EKEvent 添加一些附加字段

ios - 从 EKEventStore 获取事件并在 Swift iOS8 的 tableView 中显示

php - 如何使用加密 key 在设备端加密并在服务器端解密

iphone - UIToolBar 意外地在 UIBarButtonItem 实例上注册点击,即使在距它们相当远的地方点击也是如此

ios - 使用带 HTTPS 的 NSURLConnection 发送 POST

ios - 在EKParticipant/EKAttendee中访问电子邮件

ios - 将位置添加到 EKEvent IOS 日历

ios - UINavigationController 自定义动画阻止滑动返回工作