Search code examples
iosswiftcalendareventkitekcalendar

Swift 4 How to get all events from calendar?


I am using Swift 4.1. And I want to write a function which will collect all events from all calendars in Calendar app of iOS. Thanks to this answer on stackoverflow: How to get all Events out of a Calendar (Swift) I was able to write my own class and call it Cale. Please, look at this:

import UIKit
import EventKit

class Cale {

    private func createDate(year: Int) -> Date {
        var components = DateComponents()
        components.year = year
        components.timeZone = TimeZone(secondsFromGMT: 0)

        return Calendar.current.date(from: components)!
    }

    private let eventStore = EKEventStore()

    private func get() {
        let calendars = eventStore.calendars(for: .event)

        for calendar in calendars {
            // This checking will remove Birthdays and Hollidays callendars
            guard calendar.allowsContentModifications else {
                continue
            }

            let start = createDate(year: 2016)
            let end = createDate(year: 2025)

            print("start: \(start)")
            print("  end: \(end)")

            let predicate = eventStore.predicateForEvents(withStart: start, end: end, calendars: [calendar])

            print("predicate: \(predicate)")

            let events = eventStore.events(matching: predicate)

            for event in events {
                print("    title: \(event.title!)")
                print("startDate: \(event.startDate!)")
                print("  endDate: \(event.endDate!)")
            }
        }
    }

    func checkStatusAndGetAllEvents() {
        let currentStatus = EKEventStore.authorizationStatus(for: EKEntityType.event)

        switch currentStatus {
        case .authorized:
            //print("authorized")
            self.get()
        case .notDetermined:
            //print("notDetermined")
            eventStore.requestAccess(to: .event) { accessGranted, error in
                if accessGranted {
                    self.get()
                } else {
                    print("Change Settings to Allow Access")
                }
            }
        case .restricted:
            print("restricted")
        case .denied:
            print("denied")
        }
    }
}

Quite simple class, you can use it, it is working but with one exception. The main function there is get() In this function I am creating predicate based on two dates: start and end. As you can see start date is:

2016-01-01 00:00:00 +0000

and end date is:

2025-01-01 00:00:00 +0000

But if we run the program we will see that predicate will be like this:

CADEventPredicate start:01/01/2016, 03:00; end:01/01/2020, 03:00; cals:( 2 )

Only from 2016 to 2020, 4 years! I have tested it on different dates, but I could get predicate with 4 years interval maximum. It means, it will not give me all events! So question is: How to get all events from calendar? If it possible, without using dates!

Thank you for any future help or advice!


Solution

  • In case anyone is still wondering, Apple limited this to four years intentionally.

    From predicateForEvents(withStart:end:calendars:):

    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 is shortened to the first four years.

    If you want a range longer than that, I guess you'll have to wrap this in your own function to split it into four year chunks.