How to get responseObject into cells in UITableView - objective-c

I'm making an 'Add Friend' function, where it's possible to search on a username. I have a responeObject that contains an array of users. I only want to get the #"name" object for all the users and then list them in the TableView. If I search on "e" i get 3 results:
responseObject: (
{
id = 1;
isUsersAccount = 0;
name = Eshixf;
},
{
id = 3;
isUsersAccount = 0;
name = Neigstal;
},
{
id = 4;
isUsersAccount = 0;
name = Howie;
})
How can I get out all 3 names in 3 different cells?
And why does I get an error when I running the code with this line inside?:
NSDictionary *nameDict = [[friendRow objectAtIndex:0]objectForKey:#"name"];
It gives me this error:
-[__NSCFArray objectForKey:]: unrecognized selector sent to instance 0x7faec35f4d40
Thank you!

you can get all names with simple iteration over response.
NSArray *response = friendRow[0]; // this is result dictionaries in an array. actually it is your responseObject.
//NSMutableArray *names = [NSMutableArray new];
names = [NSMutableArray new];//if declared outside the method, use this array as a dataSource for tableView.
for(NSDictionary *dict in response)
{
[names addObject:dict[#"name"]];
}
NSLog("names %#", names);
//refresh your tableview;
[yourTableView reloadData];
EDIT for TableView:
create names in interface as
NSMutableArray *names;
in delegate method:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
[cell.textLabel setText:names[indexPath.row]];
return cell;
}
with this method, tableview will know how many cells it needs.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [names count];
}

Related

Populating table with 2 arrays

I'm trying to populate a tableview controller with objects from 2 different arrays but it crashes and gives this error
"Terminating app due to uncaught exception 'NSRangeException', reason: ' -[__NSArrayM objectAtIndex:]: index 1 beyond bounds [0 .. 0]"***
how do i fix this? below is my code:
(void)viewDidAppear:(BOOL)animated{
//[super viewDidAppear:<#animated#>];
NSManagedObjectContext *bookmanagedObjectContext = [self managedObjectContext];
NSFetchRequest *bookfetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Book"];
NSPredicate *bookpredicate =[NSPredicate predicateWithFormat:#" bookref.toproject contains[cd]%#",self.projectdb];
[bookfetchRequest setPredicate:bookpredicate];
NSSortDescriptor *booksortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"authorSurname" ascending:YES];
NSArray *booksortDescriptors = [[NSArray alloc]initWithObjects:booksortDescriptor, nil];
[bookfetchRequest setSortDescriptors:booksortDescriptors];
self.BookrefArray = [[bookmanagedObjectContext executeFetchRequest:bookfetchRequest error:nil] mutableCopy];
NSManagedObjectContext *journalmanagedObjectContext = [self managedObjectContext];
NSFetchRequest *journalfetchRequest = [[NSFetchRequest alloc] initWithEntityName:#"Journal"];
NSPredicate *journalpredicate =[NSPredicate predicateWithFormat:#" journalref.toproj contains[cd]%#",self.projectdb];
[journalfetchRequest setPredicate:journalpredicate];
NSSortDescriptor *journalsortDescriptor = [[NSSortDescriptor alloc]initWithKey:#"surname" ascending:YES];
NSArray *journalsortDescriptors = [[NSArray alloc]initWithObjects:journalsortDescriptor, nil];
[journalfetchRequest setSortDescriptors:journalsortDescriptors];
self.JournalrefArray = [[journalmanagedObjectContext executeFetchRequest:journalfetchRequest error:nil] mutableCopy];
[self.tableView reloadData];}
(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
#warning Potentially incomplete method implementation.
// Return the number of sections.
return 1;
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
#warning Incomplete method implementation.
// Return the number of rows in the section.
return (self.BookrefArray.count + self.journalrefArray.count);
}
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row];
[cell.detailTextLabel setText:[myjournal valueForKey:#"journalname"]];
[cell.textLabel setText:[NSString stringWithFormat:#"%#, %#",[myjournal valueForKey:#"surname"],[myjournal valueForKey:#"firstname"]]];
Book *mybook =[self.BookrefArray objectAtIndex:indexPath.row];
// Configure the cell...
[cell.detailTextLabel setText:[mybook valueForKey:#"bookTitle"]];
[cell.textLabel setText:[NSString stringWithFormat:#"%#, %#",[mybook valueForKey:#"authorSurname"],[mybook valueForKey:#"authorOthernames"]]];
return cell;
}
You have this error because you try to access of an element of your array that is not exist.
In fact you says that your table has "table1.count + table2.count" elements and for each cell you try to get an element in your 2 tables with the current row.
For example, if table1 has 2 items and table2 has 5 items
, your tableView will have 7 rows and "cellForRowAtIndexPath" will be called 7 times. So for index 3 you will obtains this error because your table1 has only 2 items.
To solve the problem, you should get a book OR a journal in function of this row.
For example, you can try anything like this :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cells";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (indexPath.row < self.BookrefArray.count)
{
Book *mybook =[self.BookrefArray objectAtIndex:indexPath.row];
// Configure your cell with a book
}
else
{
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row - self.BookrefArray.count];
// Configure your cell with a journal
}
return cell;
}
You can also change the order to display journals before books.
Answer :
You need to differentiate Book and Journal in -cellForRowAtIndexPath.
Explanation :
Your call for tableview's -cellForRowAtIndexPath will be dependent upon the number you're returning from tableview's -numberOfRowsInSection method.
So, for example, you've 3 objects in BookrefArray and 2 objects in journalrefArray, your tableview's -numberOfRowsInSection method will return 5 which means -cellForRowAtIndexPath will be called for 5 times.
Let's go through this line :
Journal *myjournal =[self.journalrefArray objectAtIndex:indexPath.row];
Here, it'll get indexPath.row = 5 for one case, and your journalrefArray contains only 2 objects. So, you're getting "index .. beyond bounds" error.
Update :
You can simply merge both the arrays into one.
[documentsArray addObjectsFromArray:self.BookrefArray];
[documentsArray addObjectsFromArray:self.journalrefArray];
and then in -cellForRowAtIndexPath, you can do something like this :
id document = [documentsArray objectAtIndex:indexPath.row];
if ([document isKindOfClass:Book])
{
Book *mybook = (Book *)document;
// Do something with mybook.
}
else
{
Journal *myjournal = (Journal *)document;
// Do something with myjournal.
}

how to instantiate a CD entity without being fetched

I have a program that fetches from Core Data and then within the program if something is fetches it displays the results in my UITableView.
Now my problem is that sometimes I need the user to add another UITableCell to my UITableView but my tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section counts the elements in my array which holds my ExerciseData entities.
I've tried to create an ExerciseData entity as if it was an object but this doesnt work and crashes the program.
by doing
if ([[_ed objectAtIndex:indexPath.row] weight]) {
NSLog(#"%#",_ed);
cell.weightInput.text = [NSString stringWithFormat:#"%#",[[_ed objectAtIndex:indexPath.row] weight]];
}
it throws the error CoreData: error: Failed to call designated initializer on NSManagedObject class 'ExerciseData' that made me understand that I cant initiate a CD entity like that.
then I've tried to add to the NSArray _ed a NSString and then check for the class and if the class type was a class of NSString it shouldnt try to set cell.weightInput.text
My question are 2:
1) Is there a way to initiate an entity so that I can insert it in the array and then check if is empty so that then i can validate it on a later if statement?
if that is not possible
2) How could i populate the NSArray with something that can then be validated & escalated to multimple items but also work when there is a ExerciseData?
My goal is that the person uses - addSet to create a new UITableCell for as many times the button is pressed then i need to validate whatever is inside so that if is a ExerciseData entity and the property weight is set to populate cell.weightInput.text or otherwise dont populate it
- (void) addNewSet {
ExerciseData * newEd = [[ExerciseData alloc] init];
NSMutableArray* ar = [[NSMutableArray alloc]initWithArray:_ed];
[ar addObject:newEd];
_ed = [[NSArray alloc] initWithArray:ar];
[_mytable reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
workoutCell * cell = [tableView dequeueReusableCellWithIdentifier:#"cell"];
if (!cell) {
cell = [[workoutCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"cell"];
}
cell.weightInput.text = #"";
if ( indexPath.row < [_ed count] ) {
if (![[[_ed objectAtIndex:indexPath.row] class] isKindOfClass:[NSString class]]) {
NSLog(#"%#",_ed);
cell.weightInput.text = [NSString stringWithFormat:#"%#",[[_ed objectAtIndex:indexPath.row] weight]];
}
}
//...
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if ( [_ed count] == 0 ) {
return 1;
} else {
return [_ed count];
}
}
To create a new CoreData entity you need to:
ExerciseData *data = (ExerciseData*)[NSEntityDescription insertNewObjectForEntityForName:#"ExerciseData" inManagedObjectContext:yourContext];
Make sure to save your context after!

Trying to identify selected table view cells

I'm trying to find selected people in an array. I'm correctly getting where no one is selected, however, if one person in a group is selected, all people in the group are selected.
After a long head-scratching session, I could use some help to see if there is something obvious.
This action is going on in cellForRowAtIndexPath like this:
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSLog(#"%s", __FUNCTION__);
static NSString *pCell = #"Cell";
PeopleCell *cell = (PeopleCell *)[aTableView dequeueReusableCellWithIdentifier:pCell];
if (cell == nil) {
cell = [[PeopleCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:pCell];
}
people = [peopleArray objectAtIndex:[indexPath row]];
NSString *text = [people objectForKey:#"name"];
cell.textLabel.text = text;
if (selectedPeopleinGroup.count == 0) {
//no people selected in this group
NSLog(#"none");
cell.isSelected = [selectedPeopleinGroup containsObject:text] == NO;
} else {
//there are some people in this group - find out who they are
NSLog(#"some");
NSString *key1 = [selectedPeopleinGroup valueForKey:#"personKey"];
NSString *key2 = [people valueForKey:#"personKey"];
NSLog (#"key1 %#", key1 );
NSLog (#"key2 %#", key2 );
if (key1 == key2) {
cell.isSelected = [selectedPeople containsObject:text] == YES;
} else {
cell.isSelected = [selectedPeople containsObject:text] == NO;
}
}
return cell;
}
The cell is a subclassed UITableViewCell that has a checkmark image on the left side of the cell if selected and a different image if not selected. Many thanks.
This looks odd:
NSString *key1 = [selectedPeopleinGroup valueForKey:#"personKey"];
if selectedPeopleInGroup is an array, then valueForKey: returns an array of the results of calling valueForKey on each object in the array. So you are assigning an array to a string.
I'm surprised that the compiler is not issuing a warning about this. I'm also surprised that the log statements don't show odd values.

TableView section

I have an NSArray which includes a list of keys and this array comes out of a .plist.
At this moment i write this array in a UITableView, but this is not sorted and sectionized.
I want to sort this Array and want to have Sections in this UITableView which begins with the first character of each character in this Array.
As example:
Sectionname: "A"
Celltext: "Ahorn"
I hope you get it.
My Code now:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSArray * sections = [temp allValues];
NSUInteger *tablesections = [sections count];
return tablesections;
}
And:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath: (NSIndexPath *)indexPath
NSArray * values = [temp allValues];
[EingabeListe addObjectsFromArray:values];
char szDecryptetKey[256];
sleep(0.5);
NSString *cellValue = [values objectAtIndex:indexPath.row];
const char *cString = [cellValue cStringUsingEncoding:NSASCIIStringEncoding];
DecryptKey(cString, szDecryptetKey);
NSString *pnssDecryptetKey = [NSString stringWithFormat:#"%s",szDecryptetKey];
cell.textLabel.font = [UIFont systemFontOfSize:11.0];
cell.textLabel.text = pnssDecryptetKey;
return cell;
Thanks
I probably would not leave this in a single array. I would put it into a NSDictionary where each letter of the alphabet is a bucket to for each first letter of the alphabet (and a section). Then getting the contents of a single section would be as simple as looking up the first letter you want in the dictionary.
Start by sorting your array alphabetically. This has been asked a lot of times, but here's one answer
Next, iterate over the array and add it to a dictionary based on the first letter. Each "value" in dictionary would be an array, not just a single item. So the first time you'd get to a letter (say 'g') you'd create the "g" key in the dictionary and add an NSMutable array as the value.
As a side note, I didn't add code because this sounded like a homework assignment(of course I could be wrong). While I want to help, I wouldn't want to do it for you. That said, if it's unclear or you want more help, I'd be happy to provide).
I usually use the free Sensible TableView framework for these kind of apps. You literally just throw the array to the framework and it will automatically sort and create all the sections for you. Should take you a few minutes to implement so I recommend checking it out.
Hi thanks it works pretty fine.
But i can only see the first Character of my .plist.
I think the wrong line is this one:
NSString *cellValue = [values objectAtIndex:indexPath.row];
But here is my Code:
[super viewDidLoad];
self.EingabeListe = [NSMutableArray arrayWithCapacity:20];
NSIndexPath *indexPath = 0;
alphabet = [[NSArray alloc]initWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",
#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z",#"123",nil];
datasource = [[NSMutableDictionary alloc]initWithCapacity:[alphabet count]];
int m = 1;
int n = 0;
NSArray * values = [temp allValues];
int c = [values count];
//
char szDecryptetKey[256];
sleep(0.5);
while (m != 0) {
if ( n == c){
m = 0;
}else{
NSString *cellValue = [values objectAtIndex:indexPath.row];
const char *cString = [cellValue cStringUsingEncoding:NSASCIIStringEncoding];
NSString *pnssDecryptetKey = [NSString stringWithFormat:#"%s",szDecryptetKey];
[EingabeListe addObject:pnssDecryptetKey];
pnssDecryptetKey = 0;
}
n++;
}
for(int i = 0; i<[alphabet count]; i ++)
{
NSArray *filteredArray = [EingabeListe filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF BEGINSWITH[C] %#", [alphabet objectAtIndex:i]]];
if([filteredArray count]>0)
[datasource setObject:[filteredArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)] forKey:[alphabet objectAtIndex:i]]; // Dictionary containing sorted array of data with key as alphabets
}
}
In my .plist are some Test Keys and Values like this:
Value Key
sqq hi
zzz eg
egg bb
but in my.plist i can only see:
sqq
sqq
sqq
why?
For that you need to do modification in code; I will explain.
Steps:
Initialize the alphabets array and filter use source array based on the alphabets.
Now dataSource dictionary contains array of source data filtered by alphabets.
Now number of sections will the no. of array in the dictionary.
Load the data source array for each section from the datasource dictionary.
Initialize alphabets array and datasource array:
alphabet = [[NSArray alloc]initWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",
#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z",nil];
dataSource = [[NSMutableDictionary alloc]initWithCapacity:[alphabet count]];
sourceArray = [NSArray arrayWithObjects:#"Azz",#"ax",#"aje",#"B",#"C",#"Ca",#"D",#"DD",#"E",#"EE",#"F",#"G",#"F", nil];
Filter the source array and add the data into the dictionary with key values as alphabets:
for(int i = 0; i<[alphabet count]; i ++)
{
NSArray *filteredArray = [sourceArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF BEGINSWITH[C] %#", [alphabet objectAtIndex:i]]];
if([filteredArray count]>0)
dataSource setObject:[filteredArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)] forKey:[alphabet objectAtIndex:i]]; // Dictionary containing sorted array of data with key as alphabets
}
And you need to customize the number of sections and rows delegate methods. See the sample code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[dataSource allKeys] count];
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section
{
return [[dataSource allKeys] objectAtIndex:section];
}
Entire source code:
- (void)viewDidLoad
{
[super viewDidLoad];
alphabet = [[NSArray alloc]initWithObjects:#"A",#"B",#"C",#"D",#"E",#"F",#"G",#"H",#"I",#"J",#"K",
#"L",#"M",#"N",#"O",#"P",#"Q",#"R",#"S",#"T",#"U",#"V",#"W",#"X",#"Y",#"Z",nil];
dataSource = [[NSMutableDictionary alloc]initWithCapacity:[alphabet count]];
sourceArray = [NSArray arrayWithObjects:#"Azz",#"ax",#"aje",#"B",#"C",#"Ca",#"D",#"DD",#"E",#"EE",#"F",#"G",#"F", nil];
for(int i = 0; i<[alphabet count]; i ++)
{
NSArray *filteredArray = [sourceArray filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF BEGINSWITH[C] %#", [alphabet objectAtIndex:i]]];
if([filteredArray count]>0)
[dataSource setObject:[filteredArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)] forKey:[alphabet objectAtIndex:i]]; // Dictionary containing sorted array of data with key as alphabets
}
NSLog(#"Filtered Array %#", dataSource);
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return [[dataSource allKeys] count];
}
- (NSString *)tableView:(UITableView *)aTableView titleForHeaderInSection:(NSInteger)section
{
return [[dataSource allKeys] objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[dataSource objectForKey:[[dataSource allKeys] objectAtIndex:section]] count];
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
return 20;
}
- (BOOL)tableView:(UITableView *)tableView shouldIndentWhileEditingRowAtIndexPath:(NSIndexPath *)indexPath
{
return NO;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
originalSource = [dataSource objectForKey:[[dataSource allKeys] objectAtIndex:indexPath.section]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.textLabel.text = [NSString stringWithFormat:#"%#",[originalSource objectAtIndex:indexPath.row]];
return cell;
}
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
}
Output will be like this:

cellForRowAtIndexPath getting the right data under each section

I'm stuck with a problem populating an UITableView.
I have got an NSMutableArray with customers. It looks like this:
customer
first letter="A"
customer name="Adwars Inc."
customer
first letter="A"
customer name="Amman Co."
customer
first letter="B"
customer name="Building Inc."
customer
first letter="C"
customer name="Computer Co."
So I've got an object customer, which separates me each customer. And i've got some keys for each object.
In my second NSArray i've got all my first letters, which appear in my customer data. It look like this:
A
B
C
D
G
J
M
S
Z
I was able to get my right section count and rows in section, but when i try to populate my table view it always look like this:
SCREENSHOT
HERE IS MY CODE
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"CustomerCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:MyIdentifier] autorelease];
}
for(int i = 0; i < [firstletters count]; i++)
{
if (indexPath.section == i) {
for(int count = 0 ;count < [customers count]; count++)
{
NSString *firstletter;
NSString *key;
key = [firstletters objectAtIndex:indexPath.section];
firstletter = [[customers objectAtIndex:count] objectForKey: #"FirstLetter"];
if ([key isEqualToString:firstletter]) {
cell.textLabel.text = [[customers objectAtIndex:count] objectForKey: #"S_NAME1"];
cell.detailTextLabel.text = [[customers objectAtIndex:count] objectForKey: #"s_town"];
}
}
}
}
return cell;
}
What do i have to do to make it work?
I know you have already accepted an answer, but I just wanted to offer another thought on how this might be done with data structured in a different way. If you had a dictionary where the keys were the first letter of your customers' names, and the values were the customer objects whose first letter was the same as the key, then you wouldn't have to do any looping (I don't know if you're still doing that in your solution). I made an example project (to see if this would work) that structures the data this way, except that my "objects" are just the names of companies rather than customer objects. In my table view controller I have:
- (void)viewDidLoad {
[super viewDidLoad];
self.companyDict = [NSMutableDictionary dictionary];
NSArray *aArray = [NSArray arrayWithObjects:#"Abercrombie & Fitch",#"Altera",#"Agilent",#"Allelix",#"Abbott Laboratories", nil];
NSArray *cArray = [NSArray arrayWithObjects:#"CocaCola",#"Continental",#"ConocoPhillips", nil];
NSArray *mArray = [NSArray arrayWithObjects:#"Myriad Genetics",#"Myrexis",#"Microsoft",#"McDonald's", nil];
NSArray *nArray = [NSArray arrayWithObjects:#"Nokia",#"NPS Pharmaceuticals",#"Norelco",#"Netflix",#"Nextel",#"Navistar International", nil];
[self.companyDict setValue:aArray forKey:#"A"];
[self.companyDict setValue:cArray forKey:#"C"];
[self.companyDict setValue:mArray forKey:#"M"];
[self.companyDict setValue:nArray forKey:#"N"];
self.keys = [[self.companyDict allKeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return self.keys.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self.companyDict valueForKey:[self.keys 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:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
}
NSArray *theArray = [self.companyDict valueForKey:[self.keys objectAtIndex:indexPath.section]];
cell.textLabel.text = [theArray objectAtIndex:indexPath.row];
return cell;
}
For every cell, you're iterating through all the customers, repeatedly setting (and resetting) the textLabel and detailTextLabel for every customer whose first letter matches the current section (but you're not considering whether the index of that customer in that section matches the current indexPath.row or not). This means that in your code every cell will have the textLabel and detailTextLabel for the last customer whose first letter matches the current section's first letter.
Try this TableKit library.
This case the solution will be clean and elegant:
NSMutableDictionary* sectionMap = [NSMutableDictionary dictionaryWithCapacity:30];
for(NSDictionary* c in customers) {
NSString* firstLetter = [c objectForKey:#"FirstLetter"];
NSString* name = [c objectForKey:#"S_NAME1"];
NSString* town = [c objectForKey:#"s_town"];
TKSection* section = [sectionMap objectForKey:firstLetter];
if(!section) {
section = [TKSection sectionWithCells:nil];
section.headerTitle = firstLetter;
[sectionMap setObject:section forKey:firstLetter];
}
TKCell* cell = [TKStaticCell cellWithStyle:UITableViewCellStyleSubtitle text:name detailText:town];
[section addCell:cell];
}
self.sections = [sectionMap allValues];
TRY THIS (Copy and paste this code):
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [[UITableViewCell alloc] init];
cell = nil;
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:#"CustomerCell"] autorelease];
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
}
for(int i = 0; i < [firstletters count]; i++) {
if (indexPath.section == i) {
for(int count = 0 ;count < [customers count]; count++) {
cell.textLabel.text = nil;
cell.detailTextLabel.text = nil;
NSString *firstletter = nil;
NSString *key = nil;
key = [firstletters objectAtIndex:indexPath.section];
firstletter = [[customers objectAtIndex:count] objectForKey: #"FirstLetter"];
if ([key isEqualToString:firstletter]) {
cell.textLabel.text = [[customers objectAtIndex:count] objectForKey: #"S_NAME1"];
cell.detailTextLabel.text = [[customers objectAtIndex:count] objectForKey: #"s_town"];
}
}
}
}
return cell;
}