How to monitor system calendar for changes with EventKit

If you are working with either calendar events or reminders via EventKit framework, you need keep the data up-to-date with the system calendar database.

In the previous EventKit posts I have shown how to load events, edit them, how to work with reminders and other stuff, but so far I have not covered how to monitor for changes to the system calendar database. Let's fix that now.

The solution is thankfully pretty straightforward. There is a built-in notification that is sent each time either events or reminders change. The notification is EKEventStoreChanged.

So all we need to do is to subscribe to it with NotificationCenter and reload data when we receive it. This notification has no information about what changed, so the complete reload is basically the only viable option here.

The usage of this notification can look something like this:

import Combine
var cancellables = Set<AnyCancellable>()

NotificationCenter.default.publisher(for: .EKEventStoreChanged)
    .sink { (_) in
    // calendar changed externally, reload events
    DispatchQueue.main.async {
    }.store(in: &cancellables)

I like this Combine variant because you don't have to subscribe in one place and then another @objc method that gets called.

There is one other possibility for the cases when your app is editing one particular event and you get this notification. In this case, you can call the method refresh on this event. This will reload the event data and returns true if you don't need to refetch this event. In this case you can continue editing it. Also if refresh returns false that means the event has been either deleted or somehow invalidated and according to the docs, you should not continue using it.

Uses: Xcode 12 & Swift 5.3

Filip Němeček profile photo


Filip Němeček @nemecek_f

iOS blogger and developer with interest in Python/Django. Telling other devs' stories with iOS Chat.