iOS EKEvent商店在循环中重新创建iCloud日历,不会保存本地。 [英] iOS EKEvent Store recreating iCloud calendars in a loop, won't save local.

查看:240
本文介绍了iOS EKEvent商店在循环中重新创建iCloud日历,不会保存本地。的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个奇怪的问题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 grant,NSError * error){// iOS 6支持

if(grant){
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)//日历已存在
{
event.calendar = [eventStore calendarWithIdentifier: [默认objectForKey:@我的日历]];
NSLog(@日历已存在);

} else {//创建日历

EKSource * theSource = nil;

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

[self setupCalendarWithSource:theSource withEvent:event];
}

NSLog(@事件类型:%@,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(@你好);
}

event.startDate = startDate;
event.endDate = endDate;
event.allDay = NO;
EKAlarm * alarm = [EKAlarm alarmWithRelativeOffset:-1800]; //
之前半小时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 = @我的预约;
cal.source = theSource;
[eventStore saveCalendar:cal commit:YES error:nil];
NSLog(@cal id =%@,cal.calendarIdentifier);
NSString * calendar_id = cal.calendarIdentifier;
[默认setObject:calendar_id forKey:@我的日历];
event.calendar = cal;
}


解决方案

我不知道为什么你得到这种行为,但我认为由于禁用了iCloud这一事实,系统无法对其进行查询,然后一旦你唤醒iCloud就解决了队列创建请求(但我假设)。



无论如何,我想到的第一个解决方案是以这种方式检查iCloud是否有效

  EKSource * defaultSource = [eventStore defaultCalendarForNewEvents] .source; 

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

这样做可以将您的事件正确保存到默认来源,然后保留2个日历(本地一个和云一个)彼此同步...



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



另请参阅此处的第二个答案访问以编程方式创建的日历iOS设备(这是我的想法;))



我希望我能提供帮助。



编辑:可能没有必要创建第二个日历...尝试将日历源从EKSourceTypeCalDAV更改为EKSourceTypeLocal ...不要忘记使用提交是保存日历



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



替换为:

 } else {//创建日历

EKSource * theSource = nil;

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

[self setupCalendarWithSource:theSource withEvent:event];
}

这个......

 } else {//创建日历

EKSource * theSource = [eventStore defaultCalendarForNewEvents] .source;

[self setupCalendarWithSource:theSource withEvent:event];
}

这样你就会在正确的源中创建日历(如果用户停用,则为本地日历) iCloud和CalDAV否则)



然后:



1)当用户选择停用iCloud时,应在iphone上留下日历(而不是删除)所以你有本地源中的云日历



2)当用户选择激活时,iCloud会将他的本地日历与云合并,你去了!



我希望这个帮助


I'm having a strange issue EKEventStore, iCloud and local calendars. If iCloud is enabled the Calendar is created and events are saved into the calendar as you would expect. if iCloud is turned off and you try to save an event nothing happens, however the device continues to create iCloud calendars in a loop every 3-5 seconds until iCloud is turned back on and then all of those calendars flood into iCloud as duplicates. I'm using nearly the exact code that has been referenced here on SO many times as well as in Apples Docs. I'm completely stumped as to why it's not working and there seems to be very little documentation on EKEventStore in general.

//••••••••••••••••••••••••••••••••••••••••••••••• #pragma mark – Save Event //•••••••••••••••••••••••••••••••••••••••••••••••

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

解决方案

I'm not sure why you get this behavior, but I think due to the fact that having disabled iCloud, the system cannot make queries on it and then queue creation requests that are resolved once you wake iCloud (but I'm assuming).

Anyway, the first solution that comes to my mind is to check if iCloud is active or not in this way

EKSource *defaultSource = [eventStore defaultCalendarForNewEvents].source;

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

this is done you can save your events to the default source properly and then keep the 2 calendars (the local one and the cloud one) synchronized with each other ...

Reactivation of iCloud will still be prompted to add all local calendars.

see also the second answer here Accessing programmatically created calendar on iOS device (which is where I got the idea ;) )

I hope I was helpful.

EDIT: Maybe is not necessary to create a second calendar... Try to change the source of the calendar from EKSourceTypeCalDAV to EKSourceTypeLocal ... don't forget to save calendar with commit "YES"

EDIT2: Ok just tested ...

substitute this:

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

with this ...

} else { // Create Calendar

    EKSource *theSource = [eventStore defaultCalendarForNewEvents].source;

    [self setupCalendarWithSource:theSource withEvent:event];
}

this way u will create the calendar in the right source (local if user deactivate iCloud and CalDAV otherwise)

then:

1) when user choose to deactivate iCloud should leave calendars on iphone (and not delete) so u have the cloud calendar in the local source

2) when user choose to activate iCloud will merge his local calendars with the cloud and there u go!!

i hope this help

这篇关于iOS EKEvent商店在循环中重新创建iCloud日历,不会保存本地。的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆