Событие, сохраненное в календаре, дублируется на других устройствах после синхронизации iCloud

#swift #xcode #calendar #icloud #eventkit

Вопрос:

Я пытаюсь сделать очень простую вещь: сохранить и удалить несколько событий из календаря iCloud. Мне нужно удалить и удалить несколько событий одновременно (около 100), поэтому я использую пакетную фиксацию. Я упростил свой код ниже, чтобы воспроизвести проблему.

Этот код обычно работает. Сначала он удаляет все события в течение заданного периода, затем сохраняет событие «ТЕСТ» в календаре. Проблема возникает, если этот код запускается несколько раз за короткий промежуток времени, в частности, если он запускается снова до того, как событие «ТЕСТ» завершит синхронизацию iCloud с другими устройствами через iCloud. Например, если я выполняю этот код два-три раза в секунду на iPhone, календарь на iPhone выглядит просто отлично. Однако на других устройствах с той же учетной записью iCloud (iPad и Macbook) событие «ТЕСТ» дублируется в календаре. Если я подожду хотя бы 5-6 секунд между выполнением кода, проблем не возникнет, дубликатов не будет.

Похоже, что если я удалю события из хранилища событий до того, как они фактически завершат синхронизацию с другими устройствами iCloud, они будут дублироваться на других устройствах. В оригинальном календаре устройства все выглядит нормально. На первом изображении показан iPhone (после многократного выполнения кода), на втором-календарь Macbook после синхронизации с iCloud. Календарь тестов никому не передается. При выполнении кода не происходит перехвата ошибок. Я также пытался позвонить eventStore.remove и save с commit: true немедленно, но это не имеет никакого значения.

Календарь для iPhone Календарь Macbook

So here comes the real issue. If I am adding 100 events at once and after a minute I need to remove these events and save another 100 events to the calendar, they get duplicated for sure because iCloud sync is slow with 100 new events. If I would wait 4-5 minutes between the code executions everything is superb. Nothing gets duplicated because iCloud has already finished syncing.

If I knew when iCloud calendar is done with the syncing I could just wait for it before deleting my recently saved events. But how can I know that? With one event it takes seconds. With 100 events it takes two-three, sometimes 5 minutes. What could be the proper way to batch delete and save events?

Xcode 12.5.1, Swift 5

 let eventStore = EKEventStore()
// test calendar
let calendar = eventStore.calendars(for: .event).first(where: { $0.title == "My Test Calendar" })!

// First Delete all events within period -1 and   2 hrs from now
let periodStart = Date().addingTimeInterval(-60*60) //1hr earlier
let periodEnd = Date().addingTimeInterval(60*60*2) //2hrs later

let predicate = eventStore.predicateForEvents(withStart: periodStart, end: periodEnd, calendars: [calendar])
let events = eventStore.events(matching: predicate)

events.forEach { event in
    do {
        try eventStore.remove(event, span: .thisEvent, commit: false)
    }
    catch {
        log.warning("Error removing: (error.localizedDescription)")
    }
}

// Add a new event to the calendar
let newEvent = EKEvent(eventStore: eventStore)
newEvent.calendar = calendar
newEvent.title = "TEST"
newEvent.startDate = Date() // now
newEvent.endDate = Date().addingTimeInterval(60*60) //1hr later

do {
    try eventStore.save(newEvent, span: .thisEvent, commit: false)
}
catch {
    log.warning("Error saving: (error.localizedDescription)")
}

// Commit
do {
    try eventStore.commit()
    log.debug("Commit successful.")
}
catch {
    log.warning("Error: (error.localizedDescription)")
    eventStore.reset()
}