5

奇妙な問題 EKEventStore、iCloud、およびローカル カレンダーが発生しています。iCloud が有効になっている場合、カレンダーが作成され、予定どおりにイベントがカレンダーに保存されます。iCloud がオフになっているときにイベントを保存しようとすると、何も起こりませんが、iCloud がオンに戻るまで、デバイスは 3 ~ 5 秒ごとにループで iCloud カレンダーを作成し続け、その後、それらのすべてのカレンダーが複製として iCloud に殺到します。私は、ここSOで何度も参照されているコードとほぼ同じコードを使用しています.Apples Docs. なぜそれが機能しないのか、私は完全に困惑しており、一般的に EKEventStore に関するドキュメントはほとんどないようです。

//•••••••••••••••••••••••••••••••••••••••••• # pragma mark – イベントを保存 //••••••••••••••••••••••••••••••••••••••••••••••••••••••••••• ••••</p>

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

3 に答える 3

10

なぜこのような動作になるのかはわかりませんが、iCloud を無効にしたため、システムはそれに対してクエリを実行できず、iCloud を起動すると解決される作成要求をキューに入れることができないためだと思います (ただし、仮定しています)。

とにかく、頭に浮かぶ最初の解決策は、この方法でiCloudがアクティブかどうかを確認することです

EKSource *defaultSource = [eventStore defaultCalendarForNewEvents].source;

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

これで、イベントをデフォルト ソースに適切に保存し、2 つのカレンダー (ローカル カレンダーとクラウド カレンダー) を互いに同期させることができます ...

iCloud を再アクティブ化しても、すべてのローカル カレンダーを追加するように求められます。

ここで2番目の回答も参照してくださいiOSデバイスでプログラムによって作成されたカレンダーにアクセスする(これが私がアイデアを得た場所です;))

お役に立てば幸いです。

編集:2番目のカレンダーを作成する必要はないかもしれません...カレンダーのソースを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];
}

このようにして、適切なソースでカレンダーを作成します(ユーザーが iCloud を非アクティブ化した場合はローカル、それ以外の場合は CalDAV を非アクティブ化します)

それから:

1) ユーザーが iCloud を非アクティブ化することを選択した場合、カレンダーは iPhone に残す (削除しない) 必要があるため、ローカル ソースにクラウド カレンダーがあります。

2) ユーザーが iCloud を有効にすることを選択すると、ローカルのカレンダーがクラウドにマージされます。

この助けを願っています

于 2012-12-21T14:09:28.473 に答える