Leighton
Leighton

Reputation: 6679

Populate tableView with events from iOS (swift)

I've been following "iOS8 Swift Programming Cookbook"'s section on EventKit and calendars, and I've learned a lot (especially since I'm new to programming). But the next step that I want to take is populating a tableview that I have an outlet to in my ViewController with the event data so as to have a tableview list of upcoming events. Can anyone tell me how to do this?

Here's what I have so far:

import UIKit
import EventKit
import EventKitUI


class TodayViewController: UIViewController, UITableViewDataSource {

var events: AnyObject = []

@IBOutlet weak var tableView: UITableView!

override func viewDidLoad() {
    super.viewDidLoad()

    requestCalendarAccess()

}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
}


func requestCalendarAccess() {

    let eventStore = EKEventStore()


    switch EKEventStore.authorizationStatusForEntityType(EKEntityTypeEvent){

    case .Authorized:
        readEvents()
    case .Denied:
        displayAccessDenied()
    case .NotDetermined:
        eventStore.requestAccessToEntityType(EKEntityTypeEvent, completion:
            {[weak self] (granted: Bool, error: NSError!) -> Void in
                if granted{
                    self!.readEvents()
                } else {
                    self!.displayAccessDenied()
                }
        })
    case .Restricted:
        displayAccessRestricted()
    }
}


func displayAccessDenied(){
    println("Access to the event store is denied.")
}

func displayAccessRestricted(){
    println("Access to the event store is restricted.")
}

func readEvents(){

    /* Instantiate the event store */
    let eventStore = EKEventStore()

    let icloudSource = sourceInEventStore(eventStore,
        type: EKSourceTypeCalDAV,
        title: "iCloud")

    if icloudSource == nil{
        println("You have not configured iCloud for your device.")
        return
    }

    let calendar = calendarWithTitle("Work",
        type: EKCalendarTypeCalDAV,
        source: icloudSource!,
        eventType: EKEntityTypeEvent)

    if calendar == nil{
        println("Could not find the calendar we were looking for.")
        return
    }

    /* The event starts from today, right now */
    let startDate = NSDate()

    /* The end date will be 1 day from today */
    let endDate = startDate.dateByAddingTimeInterval(24 * 60 * 60)

    /* Create the predicate that we can later pass to the
    event store in order to fetch the events */
    let searchPredicate = eventStore.predicateForEventsWithStartDate(
        startDate,
        endDate: endDate,
        calendars: [calendar!])

    /* Fetch all the events that fall between
    the starting and the ending dates */
    let events = eventStore.eventsMatchingPredicate(searchPredicate)
        as [EKEvent]

    if events.count == 0 {
        println("No events could be found")
    } else {

        // Go through all the events and print them to the console
        for event in events{

            println("Event title = \(event.title)")
            println("Event start date = \(event.startDate)")
            println("Event end date = \(event.endDate)")
        }
    }

}

func sourceInEventStore(
    eventStore: EKEventStore,
    type: EKSourceType,
    title: String) -> EKSource?{

        for source in eventStore.sources() as [EKSource]{
            if source.sourceType.value == type.value &&
                source.title.caseInsensitiveCompare(title) ==
                NSComparisonResult.OrderedSame{
                    return source
            }
        }

        return nil
}

func calendarWithTitle(
    title: String,
    type: EKCalendarType,
    source: EKSource,
    eventType: EKEntityType) -> EKCalendar?{

        for calendar in source.calendarsForEntityType(eventType).allObjects
            as [EKCalendar]{
                if calendar.title.caseInsensitiveCompare(title) ==
                    NSComparisonResult.OrderedSame &&
                    calendar.type.value == type.value{
                        return calendar
                }
        }

        return nil
}



func tableView(tableView: UITableView,
    numberOfRowsInSection section: Int) -> Int {
        return events.count
}


func tableView(tableView: UITableView,
    cellForRowAtIndexPath
    indexPath: NSIndexPath) -> UITableViewCell {

        let cell =
        tableView.dequeueReusableCellWithIdentifier("cell")
            as UITableViewCell


        cell.textLabel!.text = /*what goes here?*/
        return cell
}

Right now my events are printing to the console perfectly, but I'm not sure how to get from there to the tableview in my view controller. Any help is appreciated!

Upvotes: 0

Views: 1650

Answers (2)

user3441734
user3441734

Reputation: 17544

at first your event data should be accessible in you table delegate

func readEvents(){
...
let events = eventStore.eventsMatchingPredicate(searchPredicate)
        as [EKEvent]
...
}

but events are NOT !!! you fetch your data just locally in you function readEvents eventhough you declare a store for events in your class, you never filled it

class TodayViewController: UIViewController, UITableViewDataSource {
var events: AnyObject = []
...
}

to fill the data in you class variable just remove 'redeclaration'

    ...
    var events: [EKEvent] = []    

    func readEvents(){
        ...
        events = eventStore.eventsMatchingPredicate(searchPredicate)
                as [EKEvent]
        ...
     }

Upvotes: 1

beeef
beeef

Reputation: 2702

The function

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath:NSIndexPath) -> UITableViewCell

gets passed the parameter cellForRowAtIndexPath which contains the index of the row inside your tableview. You can access that index using indexPath.row, which you should use to access your events-Array.

So for example your function could look like this:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

    let cell = tableView.dequeueReusableCellWithIdentifier("cell") as UITableViewCell

    var event = self.events[indexPath.row]

    cell.textLabel!.text = event.eventIdentifier

    return cell
}

I don't know exactly how the EKEvent Class looks like, but Apple's Documentation of that class says there is the eventIdentifier of type String and so you can take that to test it with your tableview.

Hope you enjoy programming! :)

Upvotes: 0

Related Questions