Calendar: Populating with Data

Following the Model-View-Controller design pattern, the data source mediates between the application's data model (that is, its model objects) and the calendar view. The data source provides the calendar view object with the information it needs to display events.

Following this approach, the TKCalendarDataSource protocol should be implemnted in order to bind TKCalendar with data. This is easy because this protocol contains a single method calendar:eventsForDate:. The adopter should provide the events specific for the provided date. Here is a sample implementation of this method:

- (NSArray *)calendar:(TKCalendar *)calendar eventsForDate:(NSDate *)date
{
    NSDateComponents *components = [self.calendarView.calendar components:NSCalendarUnitYear|NSCalendarUnitMonth|NSCalendarUnitDay fromDate:date];
    components.hour = 23;
    components.minute = 59;
    components.second = 59;
    NSDate *endDate = [self.calendarView.calendar dateFromComponents:components];
    NSPredicate *predicate = [NSPredicate predicateWithFormat:@"(startDate <= %@) AND (endDate >= %@)", endDate, date];
    return [self.events filteredArrayUsingPredicate:predicate];
}
func calendar(_ calendar: TKCalendar, eventsFor date: Date) -> [Any]? {
    var components = (self.calendarView.calendar as NSCalendar).components(NSCalendar.Unit(rawValue:NSCalendar.Unit.year.rawValue | NSCalendar.Unit.month.rawValue | NSCalendar.Unit.day.rawValue), from: date)
    components.hour = 23
    components.minute = 59
    components.second = 59
    let endDate = self.calendarView.calendar.date(from: components)
    let predicate = NSPredicate(format: "(startDate <= %@) AND (endDate >= %@)", endDate! as CVarArg, date as CVarArg)
    let result:NSArray = self.events.filtered(using: predicate) as NSArray
    return result as [AnyObject]
}
public override TKCalendarEventProtocol[] EventsForDate (TKCalendar calendar, NSDate date)
{
    NSDateComponents components = calendar.Calendar.Components (NSCalendarUnit.Year | NSCalendarUnit.Month | NSCalendarUnit.Day, date);
    components.Hour = 23;
    components.Minute = 59;
    components.Second = 59;
    NSDate endDate = calendar.Calendar.DateFromComponents (components);
    List<TKCalendarEventProtocol> filteredEvents = new List<TKCalendarEventProtocol> ();
    for (int i = 0; i < this.main.Events.Length; i++) {
        TKCalendarEvent ev = (TKCalendarEvent)this.main.Events [i];
        if (ev.StartDate.SecondsSinceReferenceDate <= endDate.SecondsSinceReferenceDate && 
            ev.EndDate.SecondsSinceReferenceDate >= date.SecondsSinceReferenceDate) {
            filteredEvents.Add (ev);
        }
    }

    return filteredEvents.ToArray ();
}

In most cases TKCalendar accesses events stored on the device where the application executes. In this scenario the EventKit framework should be used. TKCalendar provides a helper data source class which loads the events from device by using the EventKit API.

As a prerequisite, the EventKit and EventKitUI frameworks should be added to the application. Now, you are ready to use the EventKit data source helper class for TKCalendar.

The simplest scenario is to create a new instance of TKCalendarEventKitDataSource class and set it as a data source for TKCalendar:

self.calendarView = [[TKCalendar alloc] initWithFrame:self.view.bounds];
self.calendarView.autoresizingMask = UIViewAutoresizingFlexibleWidth | UIViewAutoresizingFlexibleHeight;
self.calendarView.dataSource = self.dataSource;
[self.view addSubview:self.calendarView];
self.calendarView.autoresizingMask = UIViewAutoresizing(rawValue: UIViewAutoresizing.flexibleWidth.rawValue | UIViewAutoresizing.flexibleHeight.rawValue)
self.calendarView.dataSource = self.dataSource
self.view.addSubview(self.calendarView)
this.CalendarView = new TKCalendar (this.View.Bounds);
this.CalendarView.AutoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight;
this.CalendarView.DataSource = this.DataSource;
this.View.AddSubview (this.CalendarView);

However, TKCalendarEventKitDataSource supports event filtering. Adopt its TKCalendarEventKitDataSourceDelegate protocol to enable this feature.

In the cases when you want to filter only specific events, use the shouldImportEvent: method.