How to Group by day in NSDate with NSPredicate - needed to create multiple UITableView sections How to Group by day in NSDate with NSPredicate - needed to create multiple UITableView sections sql sql

How to Group by day in NSDate with NSPredicate - needed to create multiple UITableView sections


You can modify the DateSectionTitles sample project from the Apple Developer Library according to you needs.

First, you have to modify the accessor function for the transient sectionIdentifier property to create a section identifier based on year+month+day (instead of year+month only):

- (NSString *)sectionIdentifier {    // Create and cache the section identifier on demand.    [self willAccessValueForKey:@"sectionIdentifier"];    NSString *tmp = [self primitiveSectionIdentifier];    [self didAccessValueForKey:@"sectionIdentifier"];    if (!tmp) {        /*         Sections are organized by month and year. Create the section identifier         as a string representing the number (year * 10000 + month * 100 + day);         this way they will be correctly ordered chronologically regardless of         the actual name of the month.         */        NSCalendar *calendar = [NSCalendar currentCalendar];        NSDateComponents *components = [calendar components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit)                               fromDate:[self timeStamp]];        tmp = [NSString stringWithFormat:@"%d", [components year] * 10000 + [components month] * 100  + [components day]];        [self setPrimitiveSectionIdentifier:tmp];    }    return tmp;}

Second, the titleForHeaderInSection delegate method must be changed, but the idea is the same: extract year, month and day from the section identifer, and create a header title string from that:

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {    id <NSFetchedResultsSectionInfo> theSection = [[fetchedResultsController sections] objectAtIndex:section];    NSInteger numericSection = [[theSection name] integerValue];    NSInteger year = numericSection / 10000;    NSInteger month = (numericSection / 100) % 100;    NSInteger day = numericSection % 100;    // Create header title YYYY-MM-DD (as an example):    NSString *titleString = [NSString stringWithFormat:@"%d-%d-%d", year, month, day];    return titleString;}


Assuming the idea is to group the array of objects into an array of arrays of objects, the approach I would take is this, start by finding the possible values for date (or whatever you want to group by) and then actually sort it out.

NSArray *values = ...;NSArray *sorting = [values valueForKey:@"@distinctUnionOfObject.propertyToGroupBy"];NSUInteger sectionCount = [sorting count];NSMutableArray *sections = [NSMutableArray arrayWithCapacity:sectionCount];for (int i = 0; i < sectionCount; i++)    [sections addObject:[NSMutableArray array]];[values enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {    // Figure out the section for this object    NSUInteger section = [sorting indexOfObject:obj.propertyToGroupBy];    [[sections objectAtIndex:section] addObject:obj];}];// sections will contain as many sections as there were unique values// each of those values is an array containing values that matched the criteria

This can likely be optimised, but from the top of my head, seems to fit the bill.

EDIT: After going through the question once again, the propertyToGroupBy would have to normalise the value, i.e remove time components of the date, as the grouping is done by unique values (i.e comparison is based on isEqual:)