arroyot24
arroyot24

Reputation: 171

Getting event from eventId in Swift not working

In my CalendarEventsManager class, I use singleton to save an Event. I ommit calendar access permissions code here, which work OK:

import SwiftUI
import EventKit    

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

    // More code here to define event properties.
   
    do {
     try CalendarEventsManager.shared.eventStore.save(event, span: .thisEvent)
       print("Event saved on calendar, with eventId: \(event.eventIdentifier ?? "")")
   } catch {
     print("Error saving event: \(error)")
   }

This way, I obtain event.eventIdentifier string printed with no problem at all.

But later, when trying to retrieve back this Event from its eventIdentifier, I get a nil value:

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

What am I doing wrong? I'm trying with event.calendarItemIdentifier property too, with the same result. Do this ids change when closing the app? They seem to work maintaining app open.

Updated 12/11/2023 - 18:05.

After @matt response, here you have complete CalendarEventsManager class with his suggestion. It works when trying to retrieve events not closing the app. After restarting the app, any event identifier seems to change.

import SwiftUI
import EventKit

/// The class responsible of managing addition and deletion of system calendar events when adding, updating or deleting app rehearsals.
final class CalendarEventsManager {
  @AppStorage("savingsCalendar") var savingsCalendar = ""
  @AppStorage("rehearsalsDuration") var rehearsalsDuration = 900
  @AppStorage("eventsAlarmsOn") var eventsAlarmsOn = false
  @AppStorage("eventsAlarmsTime") var eventsAlarmsTime = 900
  
  // Singletons in order to keep the same EKEventStore instance app-wide. I think it's not necessary, anyway.
  static let shared = CalendarEventsManager()
  static let eventStore = EKEventStore()
  
  /// Adds an event to system calendar from a ``Rehearsal``.
  /// - Parameter rehearsal: Related ``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)")
    }
    
    /// Using calendarItemIdentifier, as eventIdentifier seems not to be reliable. But this values SEEM TO CHANGE anyway.
    rehearsal.setValue(event.calendarItemIdentifier, forKey: "eventId")
    
  }
  
  /// Deletes the event in system calendar related to a ``Rehearsal``.
  /// - Parameter rehearsal: Related ``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)")
      }
    }
  }
}

Upvotes: 2

Views: 150

Answers (0)

Related Questions