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

Swift中通过eventId获取日历事件失败问题排查

问题:通过eventIdentifier获取日历事件返回nil,重启App后ID失效

问题概述

在CalendarEventsManager单例类中,日历权限已配置且正常工作。保存事件时能成功打印event.eventIdentifier,但后续用该ID调用eventStore.event(withIdentifier:)获取事件时返回nil。尝试使用calendarItemIdentifier结果相同,且App保持打开状态时ID有效,重启后所有事件标识符似乎都发生了变化。

保存事件的代码片段

import SwiftUI
import EventKit    

final class CalendarEventsManager {
   static let shared = CalendarEventsManager()
   let eventStore = EKEventStore()

    // 此处省略定义事件属性的更多代码
   
    do {
     try CalendarEventsManager.shared.eventStore.save(event, span: .thisEvent)
       print("Event saved on calendar, with eventId: \(event.eventIdentifier ?? "")")
   } catch {
     print("Error saving event: \(error)")
   }

获取事件的代码片段

if let event = CalendarEventsManager.shared.eventStore.event(withIdentifier: eventId ?? "") {
  print("EventID: \(event.eventIdentifier ?? "")") // <- 此处为Nil
  }
}

更新内容(2023年11月12日 18:05)

App未关闭时获取事件正常,但重启App后所有事件标识符均失效。以下是完整的CalendarEventsManager类代码:

import SwiftUI
import EventKit

/// 负责在添加、更新或删除应用排练时管理系统日历事件的增删操作。
final class CalendarEventsManager {
  @AppStorage("savingsCalendar") var savingsCalendar = ""
  @AppStorage("rehearsalsDuration") var rehearsalsDuration = 900
  @AppStorage("eventsAlarmsOn") var eventsAlarmsOn = false
  @AppStorage("eventsAlarmsTime") var eventsAlarmsTime = 900
  
  // 单例模式确保全App使用同一个EKEventStore实例,个人认为并非必需。
  static let shared = CalendarEventsManager()
  static let eventStore = EKEventStore()
  
  /// 从`Rehearsal`向系统日历添加事件。
  /// - Parameter rehearsal: 关联的`Rehearsal`对象。
  func createEvent(from rehearsal: Rehearsal) {
    let event = EKEvent(eventStore: CalendarEventsManager.eventStore)
    
    event.title = NSLocalizedString("Rehearsal with ", comment: "") + (rehearsal.relatedStudent?.name)! + " (" + (rehearsal.relatedStudent?.relatedInstrument?.name)! + ")"
    event.startDate = rehearsal.date
    event.endDate = rehearsal.date?.addingTimeInterval(TimeInterval(rehearsalsDuration))
    
    if eventsAlarmsOn {
      let time = Double(eventsAlarmsTime)
      let alarm = EKAlarm(relativeOffset: -time)
      event.alarms = [alarm]
    }
    
    var worksInfo: String = ""
    var relatedWorks = [Work]()
    if rehearsal.relatedWorks?.count ?? 0 > 0 {
      for work in Array(rehearsal.relatedWorks as! Set<Work>) {
        relatedWorks.append(work)
      }
      worksInfo.append(relatedWorks.map{ "\($0.relatedComposer?.name ?? ""): \($0.title ?? "")"}.joined(separator: "\r"))
    }
    
    let notes = (rehearsal.notes.nilIfEmpty != nil) ? rehearsal.notes ?? "" : ""
    let publicInfo = rehearsal.inPublic ? NSLocalizedString("Public", comment: "") : ""
    let footText = NSLocalizedString("This is a copy of a CompingApp rehearsal. Any changes will not take any effect on app data.", comment: "")
    event.notes = "\(worksInfo)\r\(notes)\r\(publicInfo)\r---\r\(footText)"
    
    event.calendar = CalendarEventsManager.eventStore.calendar(withIdentifier: savingsCalendar)
    
    do {
      try CalendarEventsManager.eventStore.save(event, span: .thisEvent)
    } catch {
      print("Error saving event: \(error)")
    }
    
    /// 使用calendarItemIdentifier,因eventIdentifier似乎不可靠,但该值仍会变化。
    rehearsal.setValue(event.calendarItemIdentifier, forKey: "eventId")
    
  }
  
  /// 删除与`Rehearsal`关联的系统日历事件。
  /// - Parameter rehearsal: 关联的`Rehearsal`对象。
  func deleteEvent(for rehearsal: Rehearsal) {
    
    if let event = CalendarEventsManager.eventStore.calendarItem(withIdentifier: rehearsal.eventId ?? "") {
      do {
        try CalendarEventsManager.eventStore.remove(event as! EKEvent, span: .thisEvent, commit: true)
      } catch {
        print("Error deleting event: \(error)")
      }
    }
  }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 07:34:53