I'm making a title indexed event invitation list. I have an array with EventStatus objects. I'm making the _data array for table like,
for (int i = 0; i < eventStatusList.count; i++) {
NSString *firstName = ((OCEventStatus*)eventStatusList[i]).user.firstName;
[_sortedUsers setObject:((OCEventStatus*)eventStatusList[i]).user.firstName forKey:[firstName substringToIndex:1]];
}
_sortedUserTitles = [[[_sortedUsers allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] mutableCopy];
_data = [eventStatusList mutableCopy];
[self.dataTableView reloadData];
and I think this for loop thing is too slow. Is there a way to do this in a good manner? Following is the title index making up logic with UITablrViewDataSource methods.
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [_sortedUserTitles count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSString *sectionTitle = [_sortedUserTitles objectAtIndex:section];
NSArray *sectionUsers = [_sortedUsers objectForKey:sectionTitle];
return [sectionUsers count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView
{
// return animalSectionTitles;
return _alphabetArray;
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index
{
return [_sortedUserTitles indexOfObject:title];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [_sortedUserTitles objectAtIndex:section];
}
This is error because of in the _sortedUsers dictionary has a string instead of an array. How may I fix this? And also please suggest a fast, good manner to implement this title index.
If you want to create an List of Firstnames try this perhaps.
At interface:
#property(nonatomic, strong)NSMutableDictionary *dict;
#property(nonatomic, strong)NSMutableArray *alphabet;
_dict = [NSMutableDictionary new];
_alphabet = [NSMutableArray new];
[eventStatusList sortUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
OCEventStatus *ev1 = (OCEventStatus*)obj1;
OCEventStatus *ev2 = (OCEventStatus*)obj2;
return [ev1.firstName compare:ev2.firstName];
}];
for(OCEventStatus *state in eventStatusList){
NSString *firstchar = [[state.firstName substringToIndex:1] lowercaseString];
if([dict objectForKey:firstchar]==nil){
NSMutableArray *tmp = [NSMutableArray new];
[tmp addObject:state];
[_dict setObject:tmp forKey:firstchar];
[_alphabet addObject:firstChar];
}else{
[[dict objectForKey:firstchar] addObject:state];
}
}
Now you have an Array of firstnames in a Dictionary which has the first letter as the key for Example: a -> ["Alfred","Albert",...]
In the Datasource methods you have to return it like this...
-(NSInteger)numberOfSectionsInTableView:(UITableView*)tableView{
return dict.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection;(NSInteger)section
{
return [dict objectForKey:[alphabet objectAtIndex:section]].count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
OVEventStatus *state = [[dict objectForKey:[alphabet objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = state.firstName;
return cell;
}
Please try if this fits for you
Update:
If you also want to Sort the Arrays I would recommend to sort the eventListBy firstName first! So you have the correct order when you loop over the eventStatusList.
There is an array of objects (Zakazchik):
#property (strong, nonatomic) NSMutableArray *zakazchikFavoritesArray;
Each object has field #property int zakazchikCategory and can vary from 1 to 23 inclusive.
How can I create a TableView, so grouping it was on this field?
ADDED:
in viewDidLoad (after filling zakazchikFavoritesArray):
dataDictionary = [NSMutableDictionary dictionary];
for (Zakazchik *object in zakazchikFavoritesArray) {
NSMutableArray *categoryArray = dataDictionary[#(object.zakazchikCategory)];
if (categoryArray == nil) {
categoryArray = [NSMutableArray array];
dataDictionary[#(object.zakazchikCategory)] = categoryArray;
}
[categoryArray addObject:object];
}
also:
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return dataDictionary.count;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSArray *array = dataDictionary[#(section)];
return array.count;
}
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
Zakazchik *object = dataDictionary[#(indexPath.section)][#(indexPath.row)];
static NSString *CellIdentifier = #"ZakazchikCellFavorites";
ZakazchikCellFavorites *customCell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
customCell.zakazchikName.text = object.zakazchikName;
return customCell;
}
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
Zakazchik *object = dataDictionary[#(section)];
return [NSString stringWithFormat:#"%i", object.zakazchikCategory];
}
i got error:
2015-05-30 myApp[12521:484566] -[__NSArrayM zakazchikCategory]: unrecognized selector sent to instance 0x7b735f00
2015-05-30 myApp[12521:484566] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayM zakazchikCategory]: unrecognized selector sent to instance 0x7b735f00'
The most straightforward way to do this is to first organize your data in to a new data structure that sorts them by the category property. I would recommend using a dictionary that maps from category to an array of all objects that have that category value. You can transform your data like this:
NSMutableDictionary *dataDictionary = [NSMutableDictionary dictionary];
for (Zakazchik *object in zArray) {
NSMutableArray *categoryArray = dataDictionary[#(object.category)];
if (categoryArray == nil) {
categoryArray = [NSMutableArray array];
dataDictionary[#(object.zakazchikCategory)] = categoryArray;
}
[categoryArray addObject:object];
}
Then use this data structure when implementing your UITableView data source methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return dataDictionary.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSArray *array = dataDictionary[#(section)];
return array.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
Zakazchik *object = dataDictionary[#(indexPath.section)][#(indexPath.row)];
// Create your cell using the object..
}
- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSArray *array = dataDictionary[#(section)];
Zakazchik *firstObject = [array firstObject];
return [NSString stringWithFormat:#"%i", firstObject.zakazchikCategory];
}
To avoid error you can rewrite this method as follow
-(NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSMutableArray *objectArray = dataDictionary[#(section)]; // not needed
return [NSString stringWithFormat:#"Category #%i", section];
}
Because your dataDictionary contains arrays of Zakazchik not objects directly and, I guess you have another table/array with names of categories so in this method no reason to select this object
I am having an issue with the header and the cellForRow in Arabic codes below.
The codes work in English.
Can anyone see what I am doing wrong and resolve the problem?
Thanks.
Unfortunately I am unable to post the image due to the 10 reputation things..
e.g from the UITableView
A
B
Abha
Abu Dhabi
C
Bahrain
Beirut
D
- (void)setupIndexData:objects {
self.collation = [UILocalizedIndexedCollation currentCollation];
NSInteger index, sectionTitleCount = [[self.collation sectionTitles] count];
NSMutableArray *newSectionArray = [[NSMutableArray alloc] initWithCapacity:sectionTitleCount];
for (index = 0; index < sectionTitleCount; index++) {
[newSectionArray addObject:[NSMutableArray array]];
}
for (NSString *airportList in objects) {
NSInteger sectionNumber = [self.collation sectionForObject:airportList collationStringSelector:#selector(city)];
[[newSectionArray objectAtIndex:sectionNumber] addObject:airportList];
}
for (index = 0; index < sectionTitleCount; index++) {
NSMutableArray *airportListArrayForSection = [newSectionArray objectAtIndex:index];
[newSectionArray replaceObjectAtIndex:index withObject:[self.collation sortedArrayFromArray:airportListArrayForSection collationStringSelector:#selector(city)]];
}
self.sectionArray = newSectionArray;
[self.table reloadData];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[[self.collation sectionTitles] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSMutableArray *airportListsInSection = (self.sectionArray)[section];
return [airportListsInSection count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[[self.collation sectionTitles] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:section];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return [[self.collation sectionIndexTitles] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
}
- (NSInteger)tableView:(UITableView *)tableView sectionForSectionIndexTitle:(NSString *)title atIndex:(NSInteger)index {
return [self.collation sectionForSectionIndexTitleAtIndex:index];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
....
Aiports *airportLists = (self.sectionArray)[indexPath.section][indexPath.row];
cell.textLabel.text = airportLists.city;
}
I have some JSON data that I am getting from my database. I can pull it fine and load it into my table view. my issue is separating my JSON data so I can section the tableview.
JSON
[{"id":"1","name":"steve mans","phoneNumber":"(559)123-4455","showNumber":"1","greenCard":"1","expiration":"2014-02-15","driver":"1","paid":"1","watch":"1"},
{"id":"2","name":"myself and me","phoneNumber":"(559)321-6784","showNumber":"1","greenCard":"1","expiration":"2013-10-18","driver":"0","paid":"0","watch":"2"},
{"id":"4","name":"tod bellesmithson","phoneNumber":"(559)678-3421","showNumber":"0","greenCard":"1","expiration":"2013-11-22","driver":"1","paid":"0","watch":"2"},
{"id":"3","name":"John Smith","phoneNumber":"(559)123-1234","showNumber":"1","greenCard":"0","expiration":"2013-10-08","driver":"0","paid":"1","watch":"3"},
{"id":"5","name":"greg smith","phoneNumber":"559 345-1234","showNumber":"1","greenCard":"1","expiration":"2013-10-08","driver":"0","paid":"1","watch":"3"}]
What I am trying to do is, separate this data into three sections in my tableview. So I thought create three different tables and load each table into a different section of the tableview. But the information is the same in each one (id, name, phone etc.) So I ended up with one table and added a column that designates what shift people work, 'watch'. So how do I separate the data by using the watch column, so in my tableview i will have:
section one
people who work night shift
section two
people who work morning
section three
night shift
Try with this code:
NSArray *data = (NSArray)[NSJSONSerialization JSONObjectWithData:jsonData
options:NSJSONReadingMutableContainers
error:&error];
NSMutableArray *morningShift = [NSMutableArray array];
NSMutableArray *noonShift = [NSMutableArray array];
NSMutableArray *nightShift = [NSMutableArray array];
for (int i=0; i< [data count]; i++)
{
NSDictionary *item = data[i];
if (#"1" == item[#"watch"] )
{
[morningShift addObject:item];
} else if (#"2" == item[#"watch"] )
{
[noonShift addObject:item];
} else if (#"3" == item[#"watch"] )
{
[nightShift addObject:item];
}
}
try this
NSMutableArray *tableData = [NSMutableArray alloc] init];
NSArray* nameArr = [NSArray arrayWithObjects: #"1", #"2",#"3",nil];
for(int i=0; i<[nameArr count]; i++)
{
[tableData addObject:[jsonArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"watch = %#",[nameArr objectAtIndex:i]]] ];
}
TableView Delegate Methods
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [tableData count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[tableData objectAtIndex:section ] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell= nil;
//implement your logic to display the cell item;
NSArray sectionData = [tableData objectAtIndex:indexPath.section];
NSArray rowData = [sectionData objectAtIndex:indexPath.row];
return cell;
}
Please note i have not compiled the code. There is a chance of compilation error.
check for section in your cellForRowAtIndexPath method and load data accordingly,
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//initialize cell
if (indexPath.section == 0){
// load data
}
return cell;
}
dictionaryOfWebsites = [[NSMutableDictionary alloc] init];
[dictionaryOfWebsites setObject:#"http://www.site1.com" forKey:#"Site1"];
[dictionaryOfWebsites setObject:#"http://www.site2.com" forKey:#"Site2"];
[dictionaryOfWebsites setObject:#"http://www.site3.com" forKey:#"Site3"];
[dictionaryOfWebsites setObject:#"http://www.site4.com" forKey:#"Site4"];
Above is my dictionary. I want to have a tableview where the text in the UITableViewCell will say "Site1" and the subtext will have the URL.
I know this will get me all the keys
NSArray *keys = [dictionaryOfWebsites allKeys];
// values in foreach loop
for (NSString *key in keys) {
NSLog(#"%# is %#",key, [dict objectForKey:key]);
}
you're help would be greatly appreciated
If my approach is not the best one, please let me know so I can learn from your recommendations.
Try
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[dictionaryOfWebsites allKeys] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Initialize cell of style subtitle
NSArray *keys = [[dictionaryOfWebsites allKeys]sortedArrayUsingSelector:#selector(compare:)];
NSString *key = keys[indexPath.row];
cell.textLabel.text = key;
cell.detailTextLabel.text = dictionaryOfWebsites[key];
return cell;
}
Edit : It is better to have an array of dictionaries for these kind of representation.
Each dictionary with two key value pairs Title and Subtitle.
self.dataArray = [NSMutableArray array];
NSDictionary *dict = #{#"Title":#"Site1",#"Subtitle":#"http://www.site1.com"};
[dataArray addObject:dict];
//Add rest of the dictionaries to the dataArray
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [self.dataArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//Initialize cell of style subtitle
NSDictionary *dict = self.dataArray[indexPath.row];
cell.textLabel.text = dict[#"Title"];
cell.detailTextLabel.text = dict[#"Subtitle"];
return cell;
}
You could try:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//cell initialization code
NSString *title = [keys objectAtIndex:indexPath.row];
cell.textLabel.text = title;
cell.detailTextLabel.text = [dictionaryOfWebsites objectForKey:title];
return cell;
}
in that case declare keys array as a property.