Scroll down uitableview to specific date - iphone

I would like to know if I have a uitable, the title of each table items is a date and time. May I know how to code if I want the table auto scroll down to a cell with specific date e.g. Today's date? What should I code in the viewDidLoad method?
Here is my code for the table,
#interface PictureListMainTable : UITableViewController{
IBOutlet UIButton*scroll;
}
#property (strong, nonatomic) NSManagedObjectContext *managedObjectContext;
#property (strong, nonatomic) NSMutableArray *pictureListData;
#property (strong, nonatomic) IBOutlet UIButton*scroll;
- (void)readDataForTable;
-(IBAction)scrolldown:(id)sender;
#end
#synthesize managedObjectContext, pictureListData;
#synthesize scroll;
// When the view reappears, read new data for table
- (void)viewWillAppear:(BOOL)animated
{
// Repopulate the array with new table data
[self readDataForTable];
}
// Grab data for table - this will be used whenever the list appears or reappears after an add/edit
- (void)readDataForTable
{
// Grab the data
pictureListData = [CoreDataHelper getObjectsForEntity:#"Pictures" withSortKey:#"title" andSortAscending:YES andContext:managedObjectContext];
// Force table refresh
[self.tableView reloadData];
}
#pragma mark - Actions
// Button to log out of app (dismiss the modal view!)
- (IBAction)logoutButtonPressed:(id)sender
{
[self dismissModalViewControllerAnimated:YES];
}
#pragma mark - Segue methods
- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
// Get a reference to our detail view
PictureListDetail *pld = (PictureListDetail *)[segue destinationViewController];
// Pass the managed object context to the destination view controller
pld.managedObjectContext = managedObjectContext;
// If we are editing a picture we need to pass some stuff, so check the segue title first
if ([[segue identifier] isEqualToString:#"EditPicture"])
{
// Get the row we selected to view
NSInteger selectedIndex = [[self.tableView indexPathForSelectedRow] row];
// Pass the picture object from the table that we want to view
pld.currentPicture = [pictureListData objectAtIndex:selectedIndex];
}
}
#pragma mark - Table view data source
// Return the number of sections in the table
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Return the number of rows in the section (the amount of items in our array)
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [pictureListData count];
}
// Create / reuse a table cell and configure it for display
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Get the core data object we need to use to populate this table cell
Pictures *currentCell = [pictureListData objectAtIndex:indexPath.row];
// Fill in the cell contents
cell.textLabel.text = [currentCell title];
cell.detailTextLabel.text = [currentCell desc];
// If a picture exists then use it
if ([currentCell smallPicture])
{
cell.imageView.contentMode = UIViewContentModeScaleAspectFit;
cell.imageView.image = [UIImage imageWithData:[currentCell smallPicture]];
}
return cell;
}
// Swipe to delete has been used. Remove the table item
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
if (editingStyle == UITableViewCellEditingStyleDelete)
{
// Get a reference to the table item in our data array
Pictures *itemToDelete = [self.pictureListData objectAtIndex:indexPath.row];
// Delete the item in Core Data
[self.managedObjectContext deleteObject:itemToDelete];
// Remove the item from our array
[pictureListData removeObjectAtIndex:indexPath.row];
// Commit the deletion in core data
NSError *error;
if (![self.managedObjectContext save:&error])
NSLog(#"Failed to delete picture item with error: %#", [error domain]);
// Delete the row from the data source
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
#end
Thanks

Since you are dealing with dates, it's better to create an array of dates and find current date using dateComponents.
In this snippet dates is an array of NSDate instances.
NSCalendar *cal = [NSCalendar currentCalendar];
NSDate *today = [NSDate date];
[self.dates enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
NSDate *date = (NSDate *)obj;
NSDateComponents *components = [cal components:NSDayCalendarUnit
fromDate:date
toDate:today
options:0];
if ([components day]==0) {
*stop = TRUE;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
}];
EDIT :
- (void)viewWillAppear:(BOOL)animated
{
// Repopulate the array with new table data
[self readDataForTable];
NSCalendar *cal = [NSCalendar currentCalendar];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc]init];
[dateFormatter setDateFormat:#"dd.MMMM - EEEE"];
NSDate *today = [NSDate date];
[pictureListData enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
Pictures *picture = (Pictures *)obj;
NSDate *date = [dateFormatter dateFromString:picture.title];
NSDateComponents *components = [cal components:NSDayCalendarUnit
fromDate:date
toDate:today
options:0];
if ([components day]==0) {
*stop = TRUE;
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:idx inSection:0];
[self.tableView scrollToRowAtIndexPath:indexPath
atScrollPosition:UITableViewScrollPositionTop
animated:YES];
}
}];
}

Firstly find index of todays date or any other date in UITableView's dataSource like this:
I assume date format of search date and data source date are same
NSInteger index = NSNotFound;
if ([tableViewArray containsObject:dateHere]) {
index = [tableViewArray indexOfObject:dateHere];
}
Now scroll using scrollToRowAtIndexPath
[yourTableView scrollToRowAtIndexPath:NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionNone animated:YES];
EDIT : Use these ScrollPosition to your requirement
UITableViewScrollPositionNone,
UITableViewScrollPositionTop,
UITableViewScrollPositionMiddle,
UITableViewScrollPositionBottom

You have to calculate indexpath for specific date. And use this delegate to scroll down or scroll Up the UITableViewCells in TableView
[self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionNone animated:NO];
if you know positions of UITableViewCells to use
[tableView setContentOffset:CGPointMake(0,0) animated:YES];

Related

Populating UITableView with NSArray in iOS 7

A lot of the methods have deprecated in iOS 7 in order to set font, textLabel, and color for UITableView cells. I'm also just having a difficult time populating the view with these values. Here's a snippet of my code:
- (void)fetchedData:(NSData *)responseData {
//parse out the json data
NSError* error;
NSDictionary* json = [NSJSONSerialization
JSONObjectWithData:responseData
options:kNilOptions
error:&error];
NSArray* jobs = [json objectForKey:#"results"];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
jobsArray = [jobsInfo objectForKey:#"results"];
}
}
I am looping through an array of dictionaries from a GET request and parsed. I am now attempting to fill my UITableView with the following code:
-
(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [jobsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSDictionary *jobsDic = [jobsArray objectAtIndex:indexPath.row];
[cell.textLabel setText:[jobsDic objectForKey:#"jobtitle"]];
return cell;
}
Also, I have declared this is in my .h file:
NSArray *jobsDic;
Any ideas on what I'm doing wrong? Is this an iOS 7 problem?
It seems that you reinitialize jobsarray at the end of the forin loop.
You didn't mean ?
NSArray* jobs = [json objectForKey:#"results"];
NSMutableArray *jobsTemp = [[NSMutableArray alloc] initWithCapacity:jobs.count];
for(NSDictionary *jobsInfo in jobs) {
JobInfo *jobby = [[JobInfo alloc] init];
jobby.city = jobsInfo[#"city"];
jobby.company = jobsInfo[#"company"];
jobby.url = jobsInfo[#"url"];
jobby.title = jobsInfo[#"jobtitle"];
jobby.snippet = jobsInfo[#"snippet"];
jobby.state = jobsInfo[#"state"];
jobby.time = jobsInfo[#"date"];
[jobsTemp addObject:jobby];
}
self.jobsArray = jobsTemp; //set #property (nonatomic, copy) NSArray *jobsArray; in the .h
[self.tableView reloadData]; //optional only if the data is loaded after the view
In the cell for row method :
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
JobInfo *job = self.jobsArray[indexPath.row];
cell.textLabel.text = job.title;
return cell;
}
And don't forget :
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return self.jobsArray.count;
}
Update - an user suggested an edit :
It's true that count isn't a NSArray property. But as Objective-C lets us use a shortcut notation for calling method with a dot, this code works. You have to know limitation of this : if you use a NSArray subclass with a count property with a custom getter this could have side effects #property (nonatomic, strong, getter=myCustomCount) NSUInteger count. As I think code readability is to me one of most important things I prefer to use dot notation. I think Apple SHOULD implement count as readonly property so I use it this way (but it's my point of view). So for those which don't agree with me just read return [self.jobsArray count]; in the tableView:numberOfRowsInSection: method.
Change the declaration of jobsArray from NSArray to NSMutableArray.
Add an initialization at the beginning point of fetchedData method like follows.
if(!jobsArray) {
jobsArray = [NSMutableArray array];
}
else {
[jobsArray removeAllObjects];
}
Remove the following line.
jobsArray = [jobsInfo objectForKey:#"results"];
Instead of that, add the initialized object to the array at the end of for loop.
[jobsArray addObject:jobby];
Add a [tableView reloadData]; at the end of your *-(void)fetchedData:(NSData )responseData; method implementation.
Initially when you are loading the view, tableView will get populated. After you received the data, tableView will not be known that it is received.
Everything else seems good. Hope rest will work fine.

Custom KalDataSource I tried to implement it but I'm getting an error

I try using a custom kal datasource for my calendar. I succeeded in getting the data, and when I tried to run it I keep getting this error:
-[NSNull cc_componentsForMonthDayAndYear]: unrecognized selector sent to instance 0x2823fb8
My code
// KalParseDataSource.m
#import "KalParseDataSource.h"
#import <Parse/Parse.h>
#implementation KalParseDataSource
static BOOL IsDateBetweenInclusive(NSDate *date, NSDate *begin, NSDate *end)
{
return [date compare:begin] != NSOrderedAscending && [date compare:end] != NSOrderedDescending;
}
- (id)init
{
if ((self = [super init])) {
items = [[NSMutableArray alloc] init];
events= [[NSMutableArray alloc] init];
}
return self;
}
#pragma mark UITableViewDataSource protocol conformance
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = #"Filler text";
return cell;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return 0;
}
- (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate{
NSLog(#"getting data");
if ([events count] > 0) {
[delegate loadedDataSource:self];
return;
}
NSDateFormatter *fmt = [[NSDateFormatter alloc] init];
[fmt setDateFormat:#"yyyy-MM-dd hh:mm:ss"];
PFUser *user = [PFUser currentUser];
PFQuery *query = [PFQuery queryWithClassName:#"CalendarEvents"];
[query whereKey:#"user" equalTo:user];
[query findObjectsInBackgroundWithBlock:^(NSArray *objects, NSError *error) {
if (!error) {
[events removeAllObjects];
[events addObjectsFromArray:objects];
[delegate loadedDataSource:self];
} else {
NSLog(#"Error: %# %#", error, [error userInfo]);
}
}];
}
- (NSArray *)markedDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate {
return [[self tagsFrom:fromDate to:toDate] valueForKeyPath:#"date"];
}
- (void)loadItemsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
[items addObjectsFromArray:[self tagsFrom:fromDate to:toDate]];
}
- (NSArray *)tagsFrom:(NSDate *)fromDate to:(NSDate *)toDate
{
NSMutableArray *matches = [NSMutableArray array];
for (PFObject *event in events){
if (IsDateBetweenInclusive([event objectForKey:#"event_date"], fromDate, toDate)){
[matches addObject:event];
}
}
return matches;
}
- (void)removeAllItems{
[items removeAllObjects];
}
#end
My view controller holding the calendar.
#import "MainMenuViewController.h"
#import "Kal.h"
#import "KalParseDataSource.h"
#interface MainMenuViewController ()
#end
#implementation MainMenuViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
id<KalDataSource> source = [[KalParseDataSource alloc] init];
KalViewController *calendar = [[KalViewController alloc] init];
calendar.dataSource = source;
[self addChildViewController:calendar];
[calendar didMoveToParentViewController:self];
[self.view addSubview:calendar.view];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#end
I'm stuck with this for 3 days, Can anyone give simple example in using this 3rd party framework https://github.com/klazuka/Kal ? The one on the repo seems a bit complicated, I just want to use a custom data source.
it seems that the function cc_componentsForMonthDayAndYear you are calling with null just put a debug there from wherever the function is being called and check if the function being called is on NSDate and it is not released.
And you can always Enable Zombies to find the released object when crash happens. You can track if any variable gets released via setting NSZombieEnabled to YES. With zombies enabled, messages to deallocated objects will no longer behave strangely or crash in difficult-to-understand ways, but will instead log a message and die in a predictable and debugger-breakpointable way.
You can set NSZombieEnabled by the following steps.
Select Product from the menu bar above. Keep alt/option pressed and select "Test..." or "Run...".
1.
Go to the Arguments tab, and add NSZombieEnabled YES in the "Environment Variables" section.
OR
2.
Go to the Diagnostics tab, and check Enable Zombie Objects in the "Memory Management" section.

How to create a calendar like this

I want to create a week based calendar, it should show the days in UITableView as a list. Below is image i have posted to clear the required output. Have gone through google a lot, but doesn't got any solution.. Have gone throgh many calendars KAl, Tapku and also Mukhu but not got any solution for it. Please guide.
Dude try this for week and day view
https://github.com/muhku/calendar-ui?
week or day view might get you started with or if you wan to start afresh fetch events from the ios EventStore and make a datasource that feeds data to your table. Mostly all calendar components do that, you can even take that from the above component.
Use these methods to make dates:
#define DATE_COMPONENTS (NSYearCalendarUnit| NSMonthCalendarUnit | NSDayCalendarUnit | NSWeekCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit | NSWeekdayCalendarUnit | NSWeekdayOrdinalCalendarUnit)
#define CURRENT_CALENDAR [NSCalendar currentCalendar]
+ (NSDate *)nextDayFromDate:(NSDate *)date {
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:date];
[components setDay:[components day] + 1];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
return [CURRENT_CALENDAR dateFromComponents:components];
}
+ (NSDate *)previousDayFromDate:(NSDate *)date {
NSDateComponents *components = [CURRENT_CALENDAR components:DATE_COMPONENTS fromDate:date];
[components setDay:[components day] - 1];
[components setHour:0];
[components setMinute:0];
[components setSecond:0];
return [CURRENT_CALENDAR dateFromComponents:components];
}
Organise dates into a week - group those dates to form a week. Take day of week by day number using this method:
+ (NSString *)dayNameForWeekDay:(int)weekday
{
switch (weekday) {
case 1:
return #"Sunday";
break;
case 2:
return #"Monday";
break;
case 3:
return #"Tuesday";
break;
case 4:
return #"Wednesday";
break;
case 5:
return #"Thursday";
break;
case 6:
return #"Friday";
break;
case 7:
return #"Saturday";
break;
default:
break;
}
return #"";
}
And using the datasource show the events. Customizing your table is not a big deal, expanding collapsing is so simple.
I roughed out something using a tableview. The basic behavior you are looking for is to add rows when a date is selected (and hide those previously selected). I did a tableView with a section for each day, and added events below it.
I added a TableView from a xib, but should have done it in code for this setup.
//
// TCViewController.m
// TableCalendarTest
//
// Created by Brian Broom on 6/18/13.
// Copyright (c) 2013 Brian Broom. All rights reserved.
//
#import "TCViewController.h"
#interface TCViewController ()
{
int selectedSection;
}
#end
#implementation TCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 3;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if (section == selectedSection) {
return 3;
} else {
return 1;
}
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0) {
[tableView beginUpdates];
[self.tableView deselectRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:selectedSection] animated:YES];
NSMutableArray *oldRows = [[NSMutableArray alloc] init];
[oldRows addObject:[NSIndexPath indexPathForRow:1 inSection:selectedSection]];
[oldRows addObject:[NSIndexPath indexPathForRow:2 inSection:selectedSection]];
selectedSection = indexPath.section;
[tableView deleteRowsAtIndexPaths:oldRows withRowAnimation:UITableViewRowAnimationTop];
NSMutableArray *newRows = [[NSMutableArray alloc] init];
[newRows addObject:[NSIndexPath indexPathForRow:1 inSection:selectedSection]];
[newRows addObject:[NSIndexPath indexPathForRow:2 inSection:selectedSection]];
[tableView insertRowsAtIndexPaths:newRows withRowAnimation:UITableViewRowAnimationBottom];
[tableView endUpdates];
}
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
if (indexPath.row == 0) {
[cell.textLabel setText:[NSString stringWithFormat:#"Day"]];
} else {
[cell.textLabel setText:[NSString stringWithFormat:#"Event %d", indexPath.row]];
}
return cell;
}
#end
The tricky part is getting the date information, and the customization.

Selecting events using Kal calendar

I'm adding a calendar view to my app using Kal Calendar but am having problems implementing a didSelectRowAtIndexPath method on the event list. I would like to push a view controller when the user selects an event for any given day. I've tried putting the method in "KalView.m", "KalViewController.m", and "KalDataSource.m", but none are recognized. Where is the appropriate place to call such a method?
I had similar issue once, Here is how I implemented it.
#import <MTDates/NSDate+MTDates.h>
#import <ObjectiveSugar/ObjectiveSugar.h>
#import <UIImageView+WebCache.h>
#import "EventsViewController.h"
#import "EventDetailsViewController.h"
#import "EventCell.h"
#import "Event.h"
#import "KalViewController.h"
#import "CalendarViewController.h"
#implementation EventsViewController
- (id)initWithEvents:(NSArray *)_events {
self = [super init];
events = _events;
return self;
}
- (void)viewDidLoad {
[super viewDidLoad];
[self listUpdated];
[self addCalendarView];
}
- (void)listUpdated
{
NSMutableArray *allEvents = [NSMutableArray array];
[allEvents addObjectsFromArray:events];
NSArray *sortedArray = [allEvents sortedArrayUsingComparator:^NSComparisonResult(Event *obj1, Event *obj2) {
return [obj1.date compare:obj2.date];
}];
_allEvents = sortedArray;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [_allEvents count];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//custom table cell (EventCell is a view I'm initialising my rows with)
Event *event = _allEvents[indexPath.row];
NSString *reuseIdentifier = [NSString stringWithFormat:#"Cell%#%#", event.venue.identifier, event.identifier];
EventCell *cell = (EventCell*) [tableView dequeueReusableCellWithIdentifier:reuseIdentifier];
if (!cell) {
cell = [EventCell createDetailedCellWithReuseIdentifier:reuseIdentifier];
cell.nameLabel.text = event.name;
}
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
Event *event = _allEvents[indexPath.row];
EventDetailsViewController *controller = [[EventDetailsViewController alloc] initWithEvent:event];
[self.navigationController pushViewController:controller animated:YES];
}
- (void) addCalendarView{
_calenderView = [[KalViewController alloc] initWithSelectedDate:[NSDate date]];
[[self.view viewWithTag:2] addSubview:_calenderView.view]; /* depends on your requirements*/
_calenderView.view.tag = 200; /* not necessary */
[_calenderView.view setFrame:self.view.bounds];
_calenderView.dataSource = self;
_calenderView.delegate = self;
}
- (void)loadItemsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate {
//NSLog(#"%#, %#", fromDate, toDate);
// filter and pass the array to the events tableview
[self filterByDateSelected:toDate];
}
-(void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)delegate
{
/** when selecting a different month **/
}
- (void)removeAllItems
{
NSLog(#"Items Removed");
// remove all the previous items from the tableview
}
-(void) filterByDateSelected: (NSDate *)selectedDate
{
NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
[dateFormat setDateFormat:#"yyyy-MM-dd"];
NSString *theDate = [dateFormat stringFromDate:selectedDate];
NSDate *_date = [NSDate dateFromString:theDate usingFormat:#"yyyy-MM-dd"];
// filter table by selectedDate
NSArray *_dateFilteredEvents = _allEvents;
_dateFilteredEvents = [_allEvents filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(Event *evaluatedEvent, NSDictionary *bindings) {
if ([evaluatedEvent.date isEqualToDate:_date]) {
return YES;
}
return NO;
}]];
NSLog(#"%#", _dateFilteredEvents);
// uncomment the following line if you want to display list in another controller
//[self showEventsByDate:_dateFilteredEvents];
// or else refresh table after updating the list
_allEvents = _dateFilteredEvents;
[_tableView reloadData];
}
- (void) showEventsByDate:(NSArray*)events
{
if (events.count > 0) {
CalendarViewController *_controller = [[CalendarViewController alloc] initWithEventArray:events];
[self.navigationController pushViewController:_controller animated:YES];
}
}
- (void) removeCalenderView{
[_calenderView.view removeFromSuperview];
}
#end

KAL Calendar, how to implement KalDataSource so as I can show events which are in iOS in-built Calendar app?

I have integrated Kal Calendar in my app successfully, here is the method how I show the calendar
-(void)showDepartDatePicker{
NSLog(#"showDepartDatePicker");
if(_departDatePicker != nil){
[self.navigationController pushViewController:_departDatePicker animated:YES];
}else{
_departDatePicker = [[KalViewController alloc] init];
_departDatePicker.title = #"Departure Date";
_departDatePicker.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:#"Today" style:UIBarButtonItemStyleBordered target:self action:#selector(showAndSelectTodayDeparturePicker)];
_departDatePicker.kvcDelegate = self;
[self.navigationController pushViewController:_departDatePicker animated:YES];
}
}
I have added following in KalViewController.h,
#protocol KalViewControllerDelegate <NSObject>
#required
- (void)didSelectDate:(KalDate *)date andLoaded:(BOOL)loaded;
#end
and
#property (nonatomic, assign) id <KalViewControllerDelegate> kvcDelegate;
and implemented this delegate method in my viewController as
- (void)didSelectDate:(KalDate *)date andLoaded:(BOOL)loaded
{
NSLog(#"Title : %#",[self.navigationController.visibleViewController title]);
[self.navigationController popViewControllerAnimated:YES];
}
now, as per my question, I want to implement KalDataSource so as it show the day marked with events and selecting it show the event details in the table view available below Month's View.
Refer this link if you are new for Kal Calendar https://github.com/klazuka/Kal
Second Question, here is how I call delegate method from KalViewController.m
- (void)didSelectDate:(KalDate *)date
{
self.selectedDate = [date NSDate];
NSDate *from = [[date NSDate] cc_dateByMovingToBeginningOfDay];
NSDate *to = [[date NSDate] cc_dateByMovingToEndOfDay];
[self clearTable];
[dataSource loadItemsFromDate:from toDate:to];
[tableView reloadData];
[tableView flashScrollIndicators];
//line below calls my delegate method
[self.kvcDelegate didSelectDate:date andLoaded:_loaded];
}
What happens is, when I call showDepartDatePicker to push KalViewController to my navigation stack, it calls my delegate method 2 times(which should be called on date selection), then for every date selection calls that delegate method again(1 time).
Even I want to limit this calendar not to show past dates!
Please help me out on this.
Define a class which implements the KalDataSource protocol. See below example for class implementing KalDataSource protocol.
//header file
#import Kal.h"
#interface MyClass : NSObject <KalDataSource>
#property (nonatomic, weak) id<KalDataSourceCallbacks> kalCallbackDelegate;
#property (nonatomic, strong) NSArray *events;
#end
----------------------
//implementation file
- (void)presentingDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate delegate:(id<KalDataSourceCallbacks>)callbackDelegate
{
//If you already have the events between fromDate and toDate then just call
[callbackDelegate loadedDataSource:self];
//Else store the callback variable in a property and do an asyncrhonous
//call to load the events.
self.kalCallbackDelegate = callbackDelegate;
//When the Asynchronous call is done, call
[self.kalCallbackDelgate loadedDataSource:self];
}
- (void)removeAllItems
{
self.eventsForDay = nil;
}
- (NSArray *)markedDatesFrom:(NSDate *)fromDate to:(NSDate *)toDate
{
//self.events may have multiple events with the same date. This pulls only the unique dates.
//Also assumes that the object has an eventDate property for the beginning of the day
NSMutableSet *uniqueDatesSet = [NSMutableSet setWithArray:[self.events valueForKeyPath:#"#distinctUnionOfObjects.eventDate"]];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"self >= %# && self <= %#", fromDate, toDate];
NSArray *uniqueDates = [[uniqueDatesSet allObjects] filteredArrayUsingPredicate:predicate];
return uniqueDates;
}
- (void)loadItemsFromDate:(NSDate *)fromDate toDate:(NSDate *)toDate
{
//filter for the events that occur between fromDate and toDate
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"eventDate >= %# && eventDate <= %#", fromDate, toDate];
NSArray *filteredArray = [self.events filteredArrayUsingPredicate:predicate];
self.eventsForDay = [filteredArray sortedArrayUsingSelector:#selector(compareByEventTime:)];
}
To render the UITableViewCells, implement tableView:cellForRowAtIndexPath: in your KalDataSource class just like you would for a UITableView.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Event *event = [self.events objectAtIndex:indexPath.row];
static NSString *identifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (!cell) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
}
cell.textLabel.text = event.title;
return cell;
}
If you want to know when a UITableViewCell is selected, define a class implementing the UITableViewDelegate protocol and set _departDatePicker.delegate equal to that class. Then you can implement the regular UITableViewDelegate methods in that class.
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
Event *event = [self.events objectAtIndex:indexPath.row];
MyViewController *viewController = [[UIStoryboard storyboardWithName:#"iPhone" bundle:nil] instantiateViewControllerWithIdentifier:#"eventInfo"];
viewController.event = event;
[self.navigationController pushViewController:viewController animated:YES];
}