如何修复iOS日历事件保存时出现的「No start date has been set」(EKErrorDomain Code=2)错误?
修复EKErrorDomain Code=2 "No start date has been set" 问题
这个问题的核心原因很明确:你把事件的startDate和endDate赋值操作放到了DispatchQueue.main.async闭包里,但保存事件的代码却在闭包外面同步执行。
咱们捋一捋执行顺序:当eventStore.requestAccess的回调触发后,你创建了EKEvent实例,接着立刻调用DispatchQueue.main.async把属性赋值的任务抛给主队列,然后马上就执行eventStore.save(...)。这时候主队列的闭包还没来得及执行,event的startDate和endDate还是默认的nil,系统自然就会抛出“没有设置开始日期”的错误——哪怕你代码里写了赋值逻辑也没用,因为时机不对!
下面给你两种修复方案,按需选择:
方案一:去掉不必要的主队列切换(推荐)
如果你的属性赋值不需要依赖UI控件(比如例子里直接用Date()生成日期),完全不需要切换到主队列,直接同步赋值就行:
func saveTaskInCalendar() { let eventStore : EKEventStore = EKEventStore() eventStore.requestAccess(to: .event) { (granted, error) in guard granted, error == nil else { print("failed to save event with error : \(String(describing: error)) or access not granted") return } let event = EKEvent(eventStore: eventStore) // 直接同步赋值,不需要主队列 event.title = "Test" event.startDate = Date() // 建议给结束时间设置一个合理的时长,比如1小时,避免和开始时间完全相同 event.endDate = Date().addingTimeInterval(3600) event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.save(event, span: .thisEvent) // 如果需要更新UI(比如提示保存成功),再切换到主队列 DispatchQueue.main.async { // 这里写UI相关操作,比如弹出提示框 } } catch let error as NSError { print("failed to save event with error : \(error)") } } }
方案二:把保存操作也移到主队列里
如果你的属性赋值必须依赖UI(比如从文本框、日期选择器获取内容),那就把保存事件的代码也放到DispatchQueue.main.async闭包里,保证赋值完成后再执行保存:
func saveTaskInCalendar() { let eventStore : EKEventStore = EKEventStore() eventStore.requestAccess(to: .event) { (granted, error) in guard granted, error == nil else { print("failed to save event with error : \(String(describing: error)) or access not granted") return } let event = EKEvent(eventStore: eventStore) DispatchQueue.main.async { event.title = "Test" event.startDate = Date() event.endDate = Date().addingTimeInterval(3600) event.calendar = eventStore.defaultCalendarForNewEvents do { try eventStore.save(event, span: .thisEvent) // 保存成功后的UI操作 } catch let error as NSError { print("failed to save event with error : \(error)") } } } }
另外补充个小建议:尽量让endDate晚于startDate,虽然系统对相同的日期也能处理,但设置一个合理的时长(比如1小时)会更符合日历事件的逻辑,也能避免一些潜在的奇怪问题。
内容的提问来源于stack exchange,提问作者Мария G
相关产品推荐
相关产品推荐

