Reputation:
In my iPhone app I want to show a table view with section headers. I have a datasource like this(Example)
(
{date : 12-10-2014 rowdata:abc},
{date : 12-10-2014 rowdata:pqr},
{date : 12-10-2014 rowdata:xyz},
{date : 13-10-2014 rowdata:123},
{date : 13-10-2014 rowdata:780},
{date : 14-10-2014 rowdata:tuv},
)
I want to show the section header as the date - and have to show row data in it like this (just consider it as a format of table view-dates are it header views and below rows)
12-10-2014
abc
pqr
xyz
13-10-2014
123
780
13-10-2014
tuv
please give me a logic to do how to change or create new arrays with my data source, I am clear working with sectioned tableview and header views.
i can create a seperate array with dates for header view, but how can I show rowdata under every section, because in every section row starts with index 0.
Upvotes: 0
Views: 659
Reputation: 18528
You are basically asking how to categorise your rowdata
data by its date
key.
Simple. You need to do the following:
date
as keys - you can imagine them as categories - and the row data as objects stored in an array for each category.Step 1:
Create your custom data model to make data management more easier and cleaner.
Create two new files called rowDataModel.h
and rowDataModel.m
. They will be a subclass of the NSObject
class.
This is what your .h
file would look like:
#import <Foundation/Foundation.h>
@interface rowDataModel : NSObject
@property (nonatomic, retain) NSString * rowDataDate;
@property (nonatomic, retain) NSString * rowDataInformation;
-(id)initWithJSONData:(NSDictionary*)data;
@end
and in your .m
file you will have this:
#import "rowDataModel.h"
@implementation rowDataModel
@synthesize rowDataDate;
@synthesize rowDataInformation;
-(id)initWithJSONData:(NSDictionary*)data{
if (self = [super init]) {
self.rowDataDate = [data objectForKey:@"date"];
self.rowDataInformation = [data objectForKey:@"rowdata"];
}
return self;
}
@end
We are doing this as this will contain easy to work with containers. Its a good way to manage your custom json objects too.
Step 2
Now in your view controller where you will be populating the database and categorising your data, make sure you import your custom rowDataModel.h
file
NSMutableDictionary *myData = [[NSMutableDictionary alloc] init];
//Have a for loop that iterates through your array
for(NSDictionary *currentItem in serverArray){
RowData *newItem = [[RowData alloc] initWithJSONData:currentItem];
//If category the date key does not exist, then create a new category for it
if([myData objectForKey:newItem.rowDataDate] == nil){
//We want to create an array for each category that will hold all the row datas
[myDate setObject:[NSMutableArray new] forKey:newItem.rowDataDate];
}
//Grab the array from a particular category and add the current item to this category
[[myDate objectForKey:newItem.rowDataDate] addObject:newItem];
}
Now when you are populating your table delegate methods, in your titleForHeader
tableview delegate methods, you simply grab the category titles: the dates from your myData
dictionary using the allKeys
property, and call the `objectForIndex:
method for the section
counter in your delegate method, ad you use that string to set the title of your header view by using the titleForHeader
table view delegate method.
And in your cellForRowAtIndexPath:
delegate method, you simply grab the correct category in your myData
array by using the keys, and then access the individual objects in the array based on the row
count.
And thats all bro. Goodluck
disclaimer, I have not tested this code, this should work right off the bat :)
Upvotes: 2
Reputation: 38728
You could do this with arrays and dictionaries but it get's a little messy and you are probably best of creating new objects that can handle this.
I would probably start with something that looks a little like this
@interface NMKSection : NSObject
@property (nonatomic, strong) NSDate *date;
@property (nonatomic, strong) NSArray *rows;
@end
@interface NMKDataSource : NSObject
@property (nonatomic, strong) NSArray *data;
@property (nonatomic, strong) NSArray *sectionSortDescriptors;
@property (nonatomic, strong) NSArray *rowSortDescriptors;
- (NMKSection *)sectionAtIndex:(NSInteger)index;
- (void)processData;
@end
This would then mean that your UITableViewDataSource
can look very simple
- (void)methodToSetupDataSource
{
self.dataSource = [[NMKDataSource alloc] init];
self.dataSource.data = data
self.dataSource.sectionSortDescriptors = // optional;
self.dataSource.rowSortDescriptors = // optional;
[self processData];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NMKSection *section = [self.dataSource sectionAtIndex:section];
return [self.dataFormatter stringFromData:section.date];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = // get cell
id row = [self.dataSource sectionAtIndex:indexPath.section].rows[indexPath.row];
// configure cell
return cell;
}
To achieve this all the heavy lifting is hidden in the NMKDataSource
. The implementation fo NMKSection
can just be left blank as it will contain no logic
@implementation NMKSection
@end
All the hard work is started from processData
@interface NMKDataSource ()
@property (nonatomic, strong) NSArray *sections;
@end
@implementation NMKDataSource
- (id)init;
{
self = [super init];
if (self) {
_sections = [[NSMutableArray alloc] init];
}
return self;
}
- (NMKSection *)sectionAtIndex:(NSInteger)index;
{
return self.sections[index];
}
- (void)processData
{
if (self.sectionSortDescriptors) {
self.sections = [self.unsortedSections sortedArrayUsingDescriptors:self.sectionSortDescriptors];
} else {
self.sections = [self.unsortedSections copy];
}
}
- (NSDictionary *)groupedData;
{
NSMutableDictionary *groupedData = [[NSMutableDictionary alloc] init];
[self.data enumerateObjectsUsingBlock:^(NSDictionary *row, NSUInteger idx, BOOL *stop) {
NSString *key = row[@"date"];
NSMutableArray *rows = groupedData[key];
if (!rows) {
groupedData[key] = rows = [[NSMutableArray alloc] init];
}
[rows addObject:row[@"rowdata"]];
}];
return groupedData;
}
- (NSArray *)unsortedSections;
{
NSMutableArray *unsortedSections = [[NSMutableArray alloc] init];
[self.groupedData enumerateKeysAndObjectsUsingBlock:^(NSDate *date, NSArray *rows, BOOL *stop) {
[unsortedSections addObject:({
NMKSection *section = [[NMKSection alloc] init];
section.date = date;
section.rows = rows;
if (self.rowSortDescriptors) {
section.rows = [rows sortedArrayUsingDescriptors:self.rowSortDescriptors];
}
section;
})];
}];
return [unsortedSections copy];
}
@end
This was written in the browser so it's not been tested. The code it just an example of where I would probably start and develop this further until I was happy
Upvotes: 0
Reputation: 8180
The best way to do this would be creating a custom object, let's call it MyDate
. My date would have two properties: a date, and an array.
@interface MyDate
@property NSDate *date;
@property NSArray *items;
@end
You parse the string, and for each information bit, you check the date. If the date is not in the array you add it. Then you add the other string to the items
array for the appropriate MyDate object.
This way, every object in items
starts with index 0, just like the rows in each section. So managing your model this way makes it easy to handle the user interface.
Upvotes: 0