How to get all Events out of a Calendar (Swift)

18,924

Solution 1

You can try something like this

import EventKit

var titles : [String] = []
var startDates : [Date] = []
var endDates : [Date] = []

var store = EKEventStore()

let calendars = store.calendars(for: .event)

for calendar in calendars {
    if calendar.title == "Work" {
        let oneMonthAgo = Date(timeIntervalSinceNow: -30*24*3600)
        let oneMonthAfter = Date(timeIntervalSinceNow: 30*24*3600)
        let predicate =  store.predicateForEvents(withStart: oneMonthAgo, end: oneMonthAfter, calendars: [calendar])
        
        let events = store.events(matching: predicate)
        
        for event in events {
            titles.append(event.title)
            startDates.append(event.startDate)
            endDates.append(event.endDate)
        }
    }
}

(Updated with Swift 5 APIs)

Solution 2

func fetchEventsFromCalendar() -> Void {
    let status = EKEventStore.authorizationStatus(for: EKEntityType.event)
    
    switch (status) {
    case .notDetermined:
        requestAccessToCalendar()
    case .authorized:
        self.fetchEventsFromCalendar(calendarTitle: "Calendar")
        break
    case .restricted, .denied: break
        
    }
}


func requestAccessToCalendar() {
    
    eventStore.requestAccess(to: EKEntityType.event) { (accessGranted, error) in
        
        self.fetchEventsFromCalendar(calendarTitle: "Calendar")
        
    }
    
}


// MARK: Fetech Events from Calendar
func fetchEventsFromCalendar(calendarTitle: String) -> Void {
    
    //PGAEventsCalendar
    for calendar:EKCalendar in calendars! {
        
        if calendar.title == calendarTitle {
        
        let selectedCalendar = calendar
        let startDate = NSDate(timeIntervalSinceNow: -60*60*24*180)
        let endDate = NSDate(timeIntervalSinceNow: 60*60*24*180)
        let predicate = eventStore.predicateForEvents(withStart: startDate as Date, end: endDate as Date, calendars: [selectedCalendar])
        addedEvents = eventStore.events(matching: predicate) as [EKEvent]
        
        print("addedEvents : \(addedEvents)")
        
        }
    }
    
}

Make sure to give the proper title of the calendar, because different calendars have different list of events, In my case calendar with title "Calendar" was having the required events list, before giving check for this:

if calendar.title == calendarTitle {

My first list was getting overrides by list from other calendar, so I used to get only few events which were not relevant to me.

Solution 3

Swift 3.0

let eventStore = EKEventStore()
let calendars = eventStore.calendars(for: .event)

for calendar in calendars {
    if calendar.title == "Work" {

        let oneMonthAgo = NSDate(timeIntervalSinceNow: -30*24*3600)
        let oneMonthAfter = NSDate(timeIntervalSinceNow: +30*24*3600)

        let predicate = eventStore.predicateForEvents(withStart: oneMonthAgo as Date, end: oneMonthAfter as Date, calendars: [calendar])

        let events = eventStore.events(matching: predicate)

        for event in events {
            titles.append(event.title)
            startDates.append(event.startDate as NSDate)
            endDates.append(event.endDate as NSDate)
        }
    }
}
Share:
18,924
beginner_T
Author by

beginner_T

Updated on June 17, 2022

Comments

  • beginner_T
    beginner_T about 2 years

    I am kinda new to Swift, but really interested. I would like to get all the events I stored in a Calendar called "Work" and show them in a tableView. I was looking for questions like this, but the code shown there seems to be kinda old and not really working. How do I do that? The tableView should be able to show the Title, start and end-Date. Is it possible to get like all Titles in an Array of Strings. Same with the start and end? Would be awesome to get some tips!

    Update: I declared the variables outside the class. Now I tried a code that looks like this, thanks to an answer I got here, but I don't get the cells to display anything?! And Yes I already created a testEvent in my Work calendar on the simulator.

        override func viewDidAppear(animated: Bool) {
    
        let eventStore = EKEventStore()
    
        switch EKEventStore.authorizationStatusForEntityType(.Event) {
        case .Authorized:
            readEvents()
        case .Denied:
            print("Access denied")
        case .NotDetermined:
    
            eventStore.requestAccessToEntityType(.Event, completion: { (granted: Bool, NSError) -> Void in
                if granted {
                    self.readEvents()
    
                }else{
                    print("Access denied")
                }
    
    
    
            })
        default:
            print("Case Default")
        }
        self.tableView.reloadData()
    }
    
    
    
    func readEvents() {
    
    
    
        let eventStore = EKEventStore()
        let calendars = eventStore.calendarsForEntityType(.Event)
    
        for calendar in calendars {
            if calendar.source.title == "Work" {
                let oneMonthAgo = NSDate(timeIntervalSinceNow: -30*24*3600)
                let oneMonthAfter = NSDate(timeIntervalSinceNow: +30*24*3600)
    
    
                let predicate = eventStore.predicateForEventsWithStartDate(oneMonthAgo, endDate: oneMonthAfter, calendars: [calendar])
    
                var events = eventStore.eventsMatchingPredicate(predicate)
    
                for event in events {
    
                    titles.append(event.title)
                    startDates.append(event.startDate)
                    endDates.append(event.endDate)
    
    
                }
    
            }
        }
    
    
    }
    
    // MARK: - Table view data source
    
    
    
    override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // #warning Incomplete implementation, return the number of rows
        return titles.count
    }
    
    
    override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCellWithIdentifier("cell", forIndexPath: indexPath)
    
    
        cell.textLabel!.text = titles[indexPath.row]
        cell.detailTextLabel!.text = "From: \(startDates[indexPath.row]) Until: \(endDates[indexPath.row])"
        // Configure the cell...
    
        return cell
    }
    
  • beginner_T
    beginner_T over 8 years
    Thanks for your help, I'm gonna try it out!
  • beginner_T
    beginner_T over 8 years
    I finally tried it, but it's giving me an error: Error getting all calendars: Error Domain=EKCADErrorDomain Code=1013 "(null)" What do I need to do now?
  • beginner_T
    beginner_T over 8 years
    Okay I got rid of this Error, but I still can't get the events? Can you please check what I have now, I updated the original post!
  • zc246
    zc246 over 8 years
    Have you got anything in any of three arrays? What do you got for events ? What do you got for calendar?
  • beginner_T
    beginner_T over 8 years
    I just checked if I have anything in calendar and there was a long text printed... but I changed: "if calendar.source.title" to just: "if calendar.title" and now it seems to work! Thanks for you answer, it made me check whats inside the array (Actually I should have thought of that before myself :D )
  • zc246
    zc246 over 8 years
    No problem. I'll also update the answer with your help. :)
  • Eddwin Paz
    Eddwin Paz about 8 years
    Does the Job, But still need to take this process out of the main Thread. Using Queue. REgards and thanks for posting here..a answer
  • Dilip Tiwari
    Dilip Tiwari over 6 years
    have u worked with google calendar in swift @Abhishek Jain
  • Abhishek Jain
    Abhishek Jain over 6 years
    No @DilipTiwari
  • Waseem Sarwar
    Waseem Sarwar almost 5 years
    just one additional thing, initialize 'eventStore' at some where as let eventStore = EKEventStore()