Reputation: 6679
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
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
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