I have an NSArray with something similar to:
6/1/13 | Data
6/2/13 | Data
7/1/13 | Data
9/1/13 | Data
What I need to somehow get the months to create section headers - but only if they are in the array and then break the dates up into the appropriate sections. Looking like:
(Section Header)June 2013
6/1/13 | Data
6/2/13 | Data
(Section Header)July 2013
7/1/13 | Data
(skips august as no dates from august are in array)
(Section Header)September 2013
9/1/13 | Data
I am attempting to implement:
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return @"June 2013";
}
But obviously need this to dynamically update with whatever months are in the array. The dates are actually NSDates that are in the array - if that makes any difference.
I have cobbled together something that should at least compile, but which is completely untested. Basically this involves pre-processing your array and storing the results in other collections that can then serve as model objects for your UITableViewDataSource
.
Add these properties to the class that is your data source. You have to declare them differently if you are using ARC.
@property(retain) NSMutableArray* tableViewSections;
@property(retain) NSMutableDictionary* tableViewCells;
Add this method to your data source and make sure that you invoke it at some time before UITableView
invokes your first data source method. Important: Your array must contain the NSDate
objects in sorted order (the example in your question implies that this is the case).
- (void) setupDataSource:(NSArray*)sortedDateArray
{
self.tableViewSections = [NSMutableArray arrayWithCapacity:0];
self.tableViewCells = [NSMutableDictionary dictionaryWithCapacity:0];
NSCalendar* calendar = [NSCalendar currentCalendar];
NSDateFormatter* dateFormatter = [[[NSDateFormatter alloc] init] autorelease];
dateFormatter.locale = [NSLocale currentLocale];
dateFormatter.timeZone = calendar.timeZone;
[dateFormatter setDateFormat:@"MMMM YYYY"];
NSUInteger dateComponents = NSYearCalendarUnit | NSMonthCalendarUnit;
NSInteger previousYear = -1;
NSInteger previousMonth = -1;
NSMutableArray* tableViewCellsForSection = nil;
for (NSDate* date in sortedDateArray)
{
NSDateComponents* components = [calendar components:dateComponents fromDate:date];
NSInteger year = [components year];
NSInteger month = [components month];
if (year != previousYear || month != previousMonth)
{
NSString* sectionHeading = [dateFormatter stringFromDate:date];
[self.tableViewSections addObject:sectionHeading];
tableViewCellsForSection = [NSMutableArray arrayWithCapacity:0];
[self.tableViewCells setObject:tableViewCellsForSection forKey:sectionHeading];
previousYear = year;
previousMonth = month;
}
[tableViewCellsForSection addObject:date];
}
}
Now in your data source methods you can say:
- (NSInteger) numberOfSectionsInTableView:(UITableView*)tableView
{
return self.tableViewSections.count;
}
- (NSInteger) tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
id key = [self.tableViewSections objectAtIndex:section];
NSArray* tableViewCellsForSection = [self.tableViewCells objectForKey:key];
return tableViewCellsForSection.count;
}
- (NSString*) tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return [self.tableViewSections objectAtIndex:section];
}
[...]
The rest of the implementation is left as an exercise to you :-) Whenever the content of your array changes you obviously need to invoke setupDataSource:
to update the contents of tableViewSections
and tableViewCells
.
You need to convert your existing single array and create a new array of dictionaries. Each dictionary in this new array will contain two entries - one for the month and the other entry will be an array containing the data for each row associated with the month.
If you need to add a new row to this structure, see of the month is already in the list. If so, update that month's array. Otherwise create a new dictionary with the new month and a new array containing the one new row.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With