Text Search for iOS Calendar using EventKit

374 Views Asked by At

I need to search an iOS device calendar for calendar events that contain a given text in the event notes. Apple describes this procedure for a date filter, where the filter conditions are defined in an NSPredicate instance - as in the following example (from https://developer.apple.com/documentation/eventkit/retrieving_events_and_reminders#overview) and many others I could find.

var predicate: NSPredicate? = nil
if let anAgo = oneDayAgo, let aNow = oneYearFromNow {
    predicate = store.predicateForEvents(withStart: anAgo, end: aNow, calendars: nil)
}
var events: [EKEvent]? = nil
if let aPredicate = predicate {
    events = store.events(matching: aPredicate)

Now, I don't care about the dates - I actually want to search the database for all dates. I'd like to retrieve all events, all dates past and future, that contain e.g. the text "my search text" in the event notes. Can I define corresponding NSPredicate conditions (and how?) and use that for a calendar search? Some sources imply that this might be possible but I haven't seen any examples that would help me. Or is it so that the date filter is the only one that can be used this way and additional conditions would have to be checked in a second iteration?

What would be the most efficient way to do it?

2

There are 2 best solutions below

0
Aravind Vijayan On BEST ANSWER

Event kit's events(matching:) method only accepts predicates created by event kit methods. If you pass a custom NSPredicate like.

store.events(matching: NSPredicate(format: "title CONTAINS[cd] %@", "search text"))

It will crash. One possible solution is to apply filter after fetching all events.

events = store.events(matching: aPredicate).filter({ $0.title.contains("search text") })
0
AudioBubble On

Aravind Vijayan posted a perfect answer to the main question. One can only search the event database by start and end date. Within the given range, one can then filter the results by additional criteria. I'd like to add a few points regarding the "I actually want to search the database for all dates" in my question:

  1. Start and end date are required, which means it is not possible to search for "all dates". Sadly there are no other criteria one can search by.
  2. The documentation for predicateForEvents() states that time intervals of max. 4 years can be searched. If one wants so cover a larger timeframe it needs to be divided into multiple chunks of 4 years.

For performance reasons, this method matches only those events within a four-year time span. If the date range between startDate and endDate is greater than four years, it’s shortened to the first four years.

  1. The search returns all events that are completely or partially inside the given time interval. This means some precautions against duplicates are needed when searching consecutive time intervals, i.e. remove duplicates of same event ID.
  2. The search returns all instances of a recurring event within the given time interval. All have the same event ID.