Static Table View - iphone

I am creating a static table view (must be compatible with iOS 4 - so I can't use iOS 5's method).
The way I have it is that I have two sections; the first has one cell, and the second has two cells. I made two arrays, one with the title of the only cell in the first section, and the second with both titles for both cells in the second section. So my dictionary looks like this:
(NSDictionary *) {
First = (
Title1 < --- Array (1 item)
);
Second = (
"Title1", < --- Array (2 items)
Title2
);
}
The issue I have is that I need to return number of rows in a section using tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section. So my question is, how do I retrieve the section from the dictionary using NSInteger section? I would also have to do the same thing in tableView:cellForRowAtIndexPath.
Thank you

If you don't understand how dictionaries work, I'd recommend simplifying the problem. Create one array for each section, then inside your delegate methods use a switch() statement to call [array count] for the row count etc. For the section count you could still use the original dictionary with [[dictionary allKeys] count].
EDIT:
I just saw #fzwo recommends the same thing in two comments

Your best bet is an array of arrays, as has been mentioned. To avoid the complexity with dictionaries, create two NSArray ivars for the table data and the section titles.
// in viewDidLoad
tableData = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:
#"Row one title",
#"Row two title",
nil],
[NSArray arrayWithObjects:
#"Row one title",
#"Row two title",
#"Row three title",
nil],
nil];
sectionTitles = [NSArray arrayWithObjects:
#"Section one title",
#"Section two title",
nil];
// in numberOfSections:
return tableData.count;
// in numberOfRowsInSection:
return [[tableData objectAtIndex:section] count];
// in titleForHeaderInSection:
return [sectionTitles objectAtIndex:section];
// in cellForRowAtIndexPath:
...
cell.textLabel.text = [[tableData objectAtIndex:indexPath.section]
objectAtIndex:indexPath.row];
You could use other objects instead of the row titles if you need more data available to your cell.

To get the number of rows in your section you can use the following:
tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSString *key = [[dictionary allKeys] objectAtIndex: section];
return [[dictionary objectForKey:key] count];
}
And to get the cell value:
tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *key = [[dictionary allKeys] objectAtIndex: indexPath.section];
NSArray *values = [dictionary objectForKey:key];
NSString *value = [values objectAtIndex: indexPath.row];
// code to create a cell
return cell;
}

Related

Add selected cells of different sections in different arrays, UICollectionView

I want to add selected cells of UICollectionView in arrays, section wise in different arrays, means different arrays for each section. The problem is this that number of sections are dynamic. Below is my code.
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
NSString *seatV;
int cs;
NSString *secVal = [arrSeatSel objectAtIndex:indexPath.section];
NSArray *arrSplit = [secVal componentsSeparatedByString:#":"];
seatV = [arrSplit objectAtIndex:1];
cs = [seatV integerValue];
int v;
NSString *cnt = [NSString stringWithFormat:#"%#",[arrTot objectAtIndex:indexPath.section]];
v = [cnt intValue];
NSString *sect = [NSString stringWithFormat:#"%d", indexPath.section];
if(indexPath.item < v)
{
if([sectionInfo count] < cs)
{
itemPaths = [self.collectionView indexPathsForSelectedItems];
sectionInfo = [NSMutableArray arrayWithArray: [self.collectionView indexPathsForSelectedItems]];
[selectedItemsInfo setObject:sectionInfo forKey:sect];
cell=[self.collectionView cellForItemAtIndexPath:indexPath];
cell.contentView.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:#"yellow_seat.png"]];
}
else
{
[self.collectionView deselectItemAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section] animated:YES];
[sectionInfo removeAllObjects];
}
[self.collectionView deselectItemAtIndexPath:[NSIndexPath indexPathForItem:indexPath.row inSection:indexPath.section] animated:YES];
}
NSLog(#"section array:%#", sectionInfo);
NSLog(#"section array1:%#", sectionInfo1);
NSLog(#"selected seats dict:%#", selectedItemsInfo);
}
The array arrSeatSel is getting the number of sections and number of seats that can be choose from each section.
description of arr seatsel:(
"Family:2",
"Gold:3"
)
Here sections are 2 and cells that can be selected are 2. Similarly for other sections and in all cases.
arrTot is getting the total number of cells in each section
description of arrTot(
10,
10
)
array arrLevels are number of sections. and array itemPaths is adding the selected cells, and here the problem is, whichever section is it is adding selected cells, but each section has it's own limit of selecting cells. Hope you got my point, if anything clear ask freely.
In short i tell you what is happening here is there is seat map for different levels level 1, 2, etc. and for each level you can select limited seats, then those selected seats for different levels are required to add in different arrays.
Use a dictionary to store the details. section number becomes the keys and store an array of selected items corresponding to each keys
Here is outline
NSDictionary
Key:section0 value: array of selected items in section0
Key:section1 value: array of selected items in section1
Code
//Create a dictionary first
NSMutableDictionary *selectedItemsInfo = [NSMutableDictionary new];
// During selection
NSMutableArray *sectionInfo = [selectedItemsInfo objectForKey:indexPath.section];
if (sectionInfo == nil) {
NSMutableArray *array = [NSMutableArray array]
[array addObject: ] // add selected item
[selectedItemsInfo setObject:array forKey:indexPath.section];
}
else
{
[sectionInfo addObject: ] // add selected item
}
Edit (Imp code from discussion)
// Follow the below pattern
NSMutableArray *sectionInfo = [selectedItemsInfo objectForKey: [NSNumber numberWithInt:indexPath.section]];
if (sectionInfo == nil) {
NSMutableArray *array = [NSMutableArray array];
[array addObject: indexPath]; // add selected item
[selectedItemsInfo setObject:array forKey:[NSNumber numberWithInt:indexPath.section]];
}
else
{
// check the count
if([sectionInfo count] < cs)
{
[sectionInfo addObject: indexPath]; // add selected item
}
else
{
// No need to add the item. Deselect the cell
}
}
// To remove an item
sectionInfo = [selectedItemsInfo objectForKey: [NSNumber numberWithInt:indexPath.section]];
[sectionInfo removeObject:indexPath]

UITableView not reversing

I'm working on information retrieval where in the latest information in on top of UITableView. The code goes like this.
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
LoanModel* loan = _feed.products[indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" ];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:#"Cell"];
}
NSString *myString = [NSString stringWithFormat:#"%#",[loan name]];
NSArray *myWords = [myString componentsSeparatedByString:#","];
NSMutableArray *reversed = [NSMutableArray arrayWithCapacity:[myWords count]];
NSEnumerator *enumerator = [myWords reverseObjectEnumerator];
for (id element in enumerator) {
[reversed addObject:element];
}
NSMutableString *reverseString = [reversed componentsJoinedByString:#","];
cell.textLabel.text = reverseString;
return cell;
}
I'm getting the JSON object which contain two fields cid and name respectively. I'm showing only the name is tableview. But I want to show it in reverse i,e last update should show at first. But above code showing the content in reverse. IF "hello" is the content, then it shows "olleh". Please suggest me how to get the UITableView in reverse list. I'm a newbie to iOS.
If you want to have the reversed order of cells / objects they represent, you have to change
LoanModel* loan = _feed.products[indexPath.row];
to
LoanModel* loan = _feed.products[_feed.products.count - 1 - indexPath.row];
assuming that _feed.products is an NSArray.
The array you are using to display the the data in tableView, you'll need to reverse that and then display the data in tableView
NSArray* reversed = [[myArray reverseObjectEnumerator] allObjects];
you can use this to make your array objects order in reverse.
Try This:
NSArray* reversedArray = [[myWords reverseObjectEnumerator] allObjects];

Sorting NSDictionary from JSON for UITableView

I am having trouble trying to sort my NSDictionary in order, and it's been weeks and I still haven't figured it out, so I wish some one could give me a hand here...
NSDictionary data is from JSON and the data is already sorted from the server and it displayed in order in the JSON, but when it retrieved and converted to NSDicitionary, the order is all wrong...
This is the JSON
{
"categories":{
"unknownCategoryName":[
{ "key1":"value1",
"key2":"value2"
}],
"unknownCategoryName1":[
{ "key1":"value1",
"key2":"value2"
}],
"unknownCategoryName2":[
{ "key1":"value1",
"key2":"value2"
}],
"unknownCategoryName3":[
{ "key1":"value1",
"key2":"value2"
}]
}
}
The category quantity and its name will not be known until the JSON is received, so this is what I am using to get the count and setting up the tableView and the section
NSDictionary *results = [jsonString JSONValue];
NSDictionary *all = [results objectForKey:#"categories"];
self.datasource = all;
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.datasource count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = [[self.datasource allKeys] objectAtIndex:section];
return title;
}
And what I want to do is to list out the section and the section title as the order in the JSON.... rather than a chaos display like
unknownCategory3
unknownCategory1
unknownCategory
unknownCategory2
The "unknownCategory" is Product Category name, they are not in alphabet order, without any number, and they are already sorted and display in order in the JSON...
So, it would be great if you guys could help.
Thanks in advance...
Keys are not ordered in NSDictionaries, so you have to sort the keys first before using them in your table view. So, instead of using [self.datasource allKeys] to get your section titles, first create a sorted array: sorted = [[self.datasource allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)], and then use that array to get the titles: title = [sorted objectAtIndex:section].
After Edit to answer a further question:
To use the sorted array to get the values you want into your table, I think this should be close. You would have to add a property, NSArray *sorted, to your .h file, and then this in your .m (this is assuming the structure of your json is as you posted above):
NSDictionary *results = [jsonString JSONValue];
NSDictionary *all = [results objectForKey:#"categories"];
self.datasource = all;
self.sorted = [[self.datasource allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.sorted count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *title = [self.sorted objectAtIndex:section];
return title;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self.datasource valueForKey:[self.sorted objectAtIndex:section]]count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
NSArray *theArray = [self.datasource valueForKey:[self.sorted objectAtIndex:indexPath.section]];
NSString *text1 = [[theArray objectAtIndex:0] valueForKey:#"key1"];
NSString *text2 = [[theArray objectAtIndex:0] valueForKey:#"key2"];
cell.textLabel.text = [NSString stringWithFormat:#"%#\r%#",text1,text2];
cell.textLabel.numberOfLines=0; // this set the number of lines to unlimited
return cell;
}
You didn't say how you wanted to display two different values in one table row -- in this example, I concatenated them into one string with a return between the two.
Seems a strange JSON. You could have used like this
{
"categories": [
"unknownCategoryName": [
{
"key1": "value1",
"key2": "value2"
}
],
"unknownCategoryName2": [
{
"key1": "value1",
"key2": "value2"
}
]
]
}
And it is very easy to sort if you did like above.
To sort JSON provided in your question
-(NSMutableArray *)getAllKeys:(NSDictionary *)jsonDictionary{
NSDictionary *all = [results objectForKey:#"categories"];
NSMutableArray *allKeys = [all allKeys];
NSSortDescriptor *sorter = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject: sorter];
[allKeys sortUsingDescriptors:sortDescriptors];
[sorter release];
return allkeys;
}
-(void)createSortedDictionary{
NSMutableDictionary *dictionaryMutable=[NSMutableDictionary dictionary];
for(NSString *string in allkeys){
[dictionaryMutable setObject:[all objectForKey:string] forKey:string];
}
}
dictionaryMutable will hold the sorted dictionary
Did you write this JSON or are you getting it from somewhere that you can't edit? It looks malformed to me. categories should be an array and the current array placement makes no sense. If the JSON looked like this:
{
categories:[
{unknownCategoryName:
{ key1:value1,
key2:value2
}},
{unknownCategoryName2:
{ key1:value1,
key2:value2
}}
]
}
Then you could read categories into an NSArray, and your delegate methods would look like this (and display in proper order):
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [categoriesArray count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSDictionary *dict = [categoriesArray objectAtIndex:section];
NSString *title = [[dict allKeys] objectAtIndex:0];
return title;
}
I think the only way you can preserve the original order is to do the initial parsing yourself after creating a JSON string from the JSON data. If the structure of the JSON string is as you posted, you could use an NSScanner to find the strings between quote marks, and then select only the ones that have a [ after the final quotation mark to add to an array which will be your ordered array of keys. You can then create the NSDictionary using a JSON parser, and get the values by looping through your ordered keys and sending them valueForKey:.

Filling UITableView Cells from an NSMutableArray within a NSMutableDictionary

I have a NSMutableDictionary that contains NSMutableArrays. The dictionary represents divisions, and the arrays represents the departments within that division. I am trying to fill in the cells of a UITableView from the contents of the NSMutableArray. I currently have the UITableView displaying the correct amount of sections (divisions) and the correct number of cells within each division [departmentArray count];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [divisionArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSArray *temp = [divisionDict objectForKey:[divisionArray objectAtIndex:section]];
return [temp count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *temp = [divisionArray objectAtIndex:section];
if ([temp isEqualToString:#"School of Humanities and Social Sciences"])
{
temp = #"Humanities and Social Sciences";
} else if ([temp isEqualToString:#"School of Science and Mathematics"]) {
temp = #"Science and Mathematics";
} else if ([temp isEqualToString:#"School of Education"]) {
temp = #"Education";
}
return temp;
}
I have tried many different things in cellForRowAtIndexPath to display the names of the departments for each division, but I cannot get it to work. I understand I have to get the array for each key, then go through that array and get the names of each dept, but implementing that in cellForRowAtIndexPath is confusing me.
Any help would be greatly appreciated!
I think you would be better off changing your structure to have an NSMutableArray that contains NSMutableDictionarys that contain NSMutableArrays for the rows and NSStrings for the titles. This I found to be very convenient in some of the code I have been developing.
Here is how is works:
You have an NSMutableArray that has an entry for each division, that ends up being a section in the table view.
Within each entry of the array you have an NSMutableDictionary that contains a two entries, one that I used the key #"rows" for, that contains an array with the rows, and one that I used the key #"title" for, that holds the section header.
Your code then becomes:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [divisionArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSArray *rowsInSection = [[divisionArray getObjectAtIndex: section] objectForKey: #"rows"];
return [rowsInSection count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSString *rawTitle = [[divisionArray getObjectAtIndex: section] objectForKey: #"title"];
NSString *sectionTitle = [rawTitle stringByReplacingOccurrencesOfString: #"School of " withString: #""];
return sectionTitle;
}
Keeping my structure the same, I was able to figure it out, heres the lines I places in my cellForRowAtIndexPath method:
NSArray *temp = [divisionDict objectForKey:[divisionArray objectAtIndex:[indexPath section]]];
[[cell textLabel] setText:[temp objectAtIndex:[indexPath row]]];

IPhone Development - Problems on building cells

I have an app that has a lot of views including tableViews but one of them has a problem that I don't know how to solve.
When the constructor of the cell is called:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath;
the parameter cellForRowAtIndexPath:(NSIndexPath *)indexPath get a random and strange number. I'm building this tableView in the same way as others. Somebody has any idea about what is happening?
Thanks,
Claudio
The trick to indexPath is using the UITableView extention properties indexPath.section and indexPath.row.
In other words if you have a simple list of string:
self.data = [NSArray arrayWithObjects:#"One", #"Two", #"Three", nil];
then in tableView:cellForRowAtIndexPath: you want to do:
cell.textLabel.text = [self.data objectAtIndex:indexPath.row];
If you have an Array within an Array:
self.data = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:#"A.1", #"A.2", nil],
[NSArray arrayWithObjects:#"B.1", #"B.2", nil],
nil];
Then you'll want to check the section and row property:
NSArray *strings = [self.data objectAtIndex:indexPath.section];
cell.textLabel.text = [strings objectAtIndex:indexPath.row];
Make sure you return the right numbers for numberOfSectionsInTableView: and tableView:numberOfRowsInSection:.