#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
немедленно, но это не имеет никакого значения.
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()
}