My app is something like a log book. I keep an evidence of events that happen in a day. Basically, I have an Entity (displayed on a tableview) with a "date" attribute. When I save a new event, the current date is stored, using [NSDate date]. How do I get to organize the tableview so all the events will be sorted by day and displayed as such? Any hints will be appreciated!
1 Answers
You should use the sectionNameKeyPath
parameter of your NSFetchedResultsController
to section out your results by date.
You essentially set the attribute you want to use as the sectionNameKeyPath parameter, which will look like this:
fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"date"
cacheName:nil];
Then your data source delegate code will look something like this:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[fetchedResultsController sections] count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [fetchedResultsController sectionIndexTitles];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [fetchedResultsController sectionForSectionIndexTitle:title atIndex:index];
}
Edit: In order to group the items by day only you will need to create a transient property for your managed objects - essentially a date string derived from the actual date.
These go at the top of your .h / .m as usual
@property (nonatomic, strong) NSString *sectionTitle;
@synthesize sectionTitle;
Now that you've created the property, you want to override its accessor to actually set up the title when it is requested.
-(NSString *)sectionTitle
{
[self willAccessValueForKey:@"date"];
NSString *temp = sectionTitle;
[self didAccessValueForKey:@"date"];
if(!temp)
{
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:@"d MMMM yyyy"]; // format your section titles however you want
temp = [formatter stringFromDate:date];
sectionTitle = temp;
}
return temp;
}
Note that this code actually checks to see if the sectionTitle is already cached and just re-uses it without recreating it. If you are expecting or allowing the date for past objects to change, the sectionTitle will need to be updated as well, if that is the case, you need to also overwrite the mutator for the date itself, and add a line for it to clear the sectionTitle (so that the next time the title is requested, it will be recreated).
- (void)setDate:(NSDate *)newDate {
// If the date changes, the cached section identifier becomes invalid.
[self willChangeValueForKey:@"date"];
[self setPrimitiveTimeStamp:newDate];
[self didChangeValueForKey:@"date"];
[self setSectionTitle:nil];
}
And finally you should just changed the sectionNameKeyPath
for your fetchedResultsController
to @"sectionTitle"
.
Apple has a sample project you can look at if you want to see something similar in action.
-
Thanks. Now I'm stuck at the part where there's a section for each object instead of being grouped – PonyLand Jun 26 '12 at 10:17
-
Oh right! This is because it is using the whole date object which contains the actual hours/minutes/seconds rather than just the day. I am adding the code to the bottom of my answer. – Dima Jun 26 '12 at 13:59
-
1Solved it :) thank you very much lolcat! Hope this will be helpful for future noobs like me – PonyLand Jun 26 '12 at 15:08