首页 > 解决方案 > 保存到日历的 EKEvent 会在 iCloud 同步后在其他设备上重复

问题描述

我正在尝试做一件非常基本的事情:从 iCloud 日历中保存和删除多个事件。我需要一次删除和删除几个事件(大约 100 个),所以我使用批量提交。我在下面简化了我的代码以复制问题。

此代码通常有效。首先它会删除给定时间段内的所有事件,然后将“TEST”事件保存到日历中。如果此代码在短时间内运行多次,更具体地说,如果它在“TEST”事件完成 iCloud 通过 iCloud 同步到其他设备之前再次运行,则会出现问题。例如,如果我在 iPhone 上每秒执行 2-3 次此代码,则日历在 iPhone 上看起来还不错。但是,在具有相同 iCloud 帐户(iPad 和 Macbook)的其他设备上,“测试”事件会在日历中重复。如果我在代码执行之间至少等待 5-6 秒就没有问题,没有重复。

看起来如果我在事件真正完成同步到其他 iCloud 设备之前从事件存储中删除事件,它们会在其他设备上复制。在原始设备日历上看起来没有任何问题。第一张图片显示 iPhone(多次执行代码后),第二张是 iCloud 同步后的 Macbook 日历。考试日历不与任何人共享。代码运行时没有错误捕获。我也尝试立即调用eventStore.removeand savecommit: true但没有区别。

iPhone 日历 Macbook 日历

所以真正的问题来了。如果我一次添加 100 个事件,并且在一分钟后我需要删除这些事件并将另外 100 个事件保存到日历中,它们肯定会重复,因为 iCloud 同步对于 100 个新事件很慢。如果我在代码执行之间等待 4-5 分钟,那么一切都很棒。因为 iCloud 已经完成同步,所以没有任何内容被复制。

如果我知道 iCloud 日历何时完成同步,我可以在删除我最近保存的事件之前等待它。但是我怎么知道呢?对于一个事件,它需要几秒钟。100 个事件需要两到三分钟,有时需要 5 分钟。批量删除和保存事件的正确方法是什么?

Xcode 12.5.1、斯威夫特 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()
}

标签: swiftxcodecalendaricloudeventkit

解决方案


推荐阅读