You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何修复iCalendar事件保存时的EKErrorDomain Code=11及重复事件问题

修复iCalendar事件插入的EKErrorDomain Code=11错误及重复事件问题

我来帮你搞定这两个问题!先拆解下错误根源,再给你修复后的完整代码:

问题原因分析

1. EKErrorDomain Code=11(对象属于不同存储)错误

这个错误的核心是你在循环里直接复用了events数组里的现有EKEvent对象——这些对象可能已经属于另一个事件存储实例,或者绑定到了不属于当前store的日历上。当你尝试修改并保存这些"外来"对象时,系统就会抛出"对象属于不同存储"的错误。

2. 重复事件问题

你的双层循环逻辑有问题:外层遍历现有events,内层遍历假日列表,只要某个现有事件和当前假日不匹配,就插入一次假日。这会导致同一个假日被多次插入(比如现有10个事件,假日和其中9个不匹配,就会插入9次)。而且你的重复判断逻辑也不对,应该是检查假日是否已经存在于日历中,而不是拿现有事件逐个对比。


修复方案&优化后的代码

// 先封装一个方法,检查某个假日是否已经存在于目标日历中
func isHolidayExists(holiday: Holiday, in store: EKEventStore) -> Bool {
    guard let startDate = holiday.start?.date,
          let endDate = holiday.end?.date,
          let summary = holiday.summary,
          let targetCalendar = store.defaultCalendarForNewEvents else {
        return false
    }
    
    // 创建查询谓词,匹配日期范围和目标日历
    let predicate = store.predicateForEvents(withStart: startDate, end: endDate, calendars: [targetCalendar])
    let existingEvents = store.events(matching: predicate)
    
    // 检查是否有相同标题的事件存在
    return existingEvents.contains { $0.title == summary }
}

// 处理假日插入的主逻辑
for holiday in holidayArray ?? [] {
    // 先检查当前假日是否已经存在,存在则跳过
    guard !isHolidayExists(holiday: holiday, in: eventStore) else {
        print("\(holiday.summary ?? "Unknown") 已存在于日历中,跳过")
        continue
    }
    
    // 校验假日数据完整性,避免强制解包崩溃
    guard let startDate = holiday.start?.date,
          let endDate = holiday.end?.date,
          let summary = holiday.summary,
          let targetCalendar = eventStore.defaultCalendarForNewEvents else {
        print("假日数据不完整,跳过本次插入")
        continue
    }
    
    // 创建全新的EKEvent实例,关联当前的eventStore
    let newEvent = EKEvent(eventStore: eventStore)
    newEvent.title = summary
    newEvent.startDate = startDate
    newEvent.endDate = endDate
    newEvent.calendar = targetCalendar
    
    // 保存事件
    do {
        try eventStore.save(newEvent, span: .thisEvent)
        print("✅ 成功保存事件:\(summary)")
    } catch let error as NSError {
        print("❌ 保存事件失败:\(error.localizedDescription),错误码:\(error.code)")
    }
}

关键优化点说明

  • 彻底解决Code=11错误:每次创建全新的EKEvent实例,并明确关联当前的eventStore,避免复用"外来"事件对象。
  • 精准的重复检查:通过EKEventStore的官方查询API直接查找是否存在相同日期和标题的事件,比双层循环高效且准确。
  • 安全的可选值处理:用guard let做可选绑定,彻底避免强制解包!导致的崩溃问题。
  • 简化逻辑结构:直接遍历假日列表,逐个检查并插入,代码逻辑更清晰易懂。

内容的提问来源于stack exchange,提问作者Ricardo Milos

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.11 08:01:48