NSMutableArray, pList, Tableview muddle and meltdown - iphone

I have a preferences view which shows a different table view depending on which Segmented Control is clicked.
I hard coded some NSMutableArrays to test basic principles:
prefsIssuesList = [[NSMutableArray alloc] init];
[prefsIssuesList addObject:#"Governance"];
[prefsIssuesList addObject:#"Innovation and technology"];
...etc
prefsIndustriesList = [[NSMutableArray alloc] init];
[prefsIndustriesList addObject:#"Aerospace and defence"];
... etc
prefsServicesList = [[NSMutableArray alloc] init];
[prefsServicesList addObject:#"Audit and assurance"];
...etc
currentArray = [[NSMutableArray alloc] init];
currentArray = self.prefsIssuesList;
Then reload the tableview with currentArray, adding a UITableViewCellAccessoryCheckmark.
Everything works fine.
But now I want to store wether the checkmark is on or off in a pList file, and read this back in.
Ideally want to a plist like this
Root Dictionary
Issues Dictionary
Governance Number 1
Innovation and technology Number 0
etc
I've got as far as working this out
// Designate plist file
NSString *path = [[NSBundle mainBundle] pathForResource: #"issues" ofType:#"plist"];
// Load the file into a Dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allNames= dict;
[dict release];
NSLog(#"Dict is %#", allNames); // All the data in the pList file
NSMutableArray *issueSection = [allNames objectForKey:#"Issues"];
NSLog(#"Issues is %#", issueSection); // The data is the Issues Section
NSString *issueVal = [issueSection objectForKey:#"Governance"];
NSLog(#"Governance is %#", issueVal); //The value of the Governance key
But what I really want to do is loop through the Issues Dictionary and get the key/value pairs so
key = cell.textLabel.text
value = UITableViewCellAccessoryCheckmark / UITableViewCellAccessoryNone
depending wether it's 1 or 0
I'm assuming that I can still assign one of the three NSMutableArrays to currentArray as I did in the hardcoded version, and use currentArray to reload the tableview.
Then amend this code to build the tableview
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [keys objectAtIndex:section];
NSArray *nameSection = [names objectForKey:key];
static NSString *CellIdentifier = #"Cell";
//UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell=[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier: CellIdentifier] autorelease];
}
cell.textLabel.text = [nameSection objectAtIndex:row];
return cell;
But my brain has melted, I've spent about six hours today reading up on pLists, NSArrays, NSMutableDisctionaries, standardUserDefaults to little avail.
I've managed to UITableViews inside UINavigationViews, use SegmentedControls, download asynchronous XML, but now I'm finally stuck, or fried, or both. Over what should be fairly simple key/value pairs.
Anyone care to give me some idiot pointers?

Typing it out led to another post with that one little word I needed to get me back on track :)
Use key/value pairs in a pList to stipulate the name of the cell and wether it was selected or not by the user.
plist is based on a structure like this
Root Dictionary
Services Dictionary
Peaches String 1
Pumpkin String 0
Here's how I grabbed three Dictionary arrays from a pList and used the key/value pairs to reload a tableview depending on which segmentControl was touched:
- (void)viewDidLoad {
[super viewDidLoad];
// Designate plist file
NSString *path = [[NSBundle mainBundle] pathForResource: #"issues" ofType:#"plist"];
// Load the file into a Dictionary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.allNames= dict;
[dict release];
// Create the Named Dictionaries from Dictionary in pLIst
NSMutableDictionary *allIssues = [self.allNames objectForKey:#"Issues"];
self.prefsIssuesList = allIssues;
[allIssues release];
NSMutableDictionary *allIndustries = [self.allNames objectForKey:#"Industries"];
self.prefsIndustriesList = allIndustries;
[allIndustries release];
NSMutableDictionary *allServices = [self.allNames objectForKey:#"Services"];
self.prefsServicesList = allServices;
[allServices release];
// Assign the current Dictionary to out placeholder Dictionary
currentDict = [[NSMutableDictionary alloc] init];
currentDict = self.prefsIssuesList;
}
Then styling the table cells
- (UITableViewCell *)tableView:(UITableView *)prefsTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger row = [indexPath row];
NSArray *keysArray = [self.currentDict allKeys];
NSString *theKey = [keysArray objectAtIndex:row];
NSString *theValue = [self.currentDict objectForKey: [keysArray objectAtIndex:row]];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.prefsTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if(cell == nil) {
cell=[[[UITableViewCell alloc]
initWithFrame:CGRectZero
reuseIdentifier: CellIdentifier] autorelease];
}
cell.textLabel.text = theKey;
if (theValue == #"0") {
cell.accessoryType = UITableViewCellAccessoryNone;
}else {
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
return cell;
}
The if clause at the end doesn't seem to be working, I'll post that as a new question (unless anyone comments quickly!)
Finally the segmentControls assign the different dictionaries to the placeholder array and reload the tableview
This took me a very long day to figure out (as a noobie) so I hope it helps someone
-(IBAction) segmentedControlIndexChanged{
switch (self.segmentedControl.selectedSegmentIndex) {
case 0:
//currentArray = self.prefsIssuesList;
currentDict = self.prefsIssuesList;
break;
case 1:
//currentArray = self.prefsIndustriesList;
currentDict = self.prefsIndustriesList;
break;
case 2:
//currentArray = self.prefsServicesList;
currentDict = self.prefsServicesList;
break;
default:
//currentArray = self.prefsIssuesList;
currentDict = self.prefsIssuesList;
break;
}
[prefsTableView reloadData];
}
Shout if there's a neater or better way of d

Related

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];

Why am I seeing a crash when displaying this table view?

I am designing a simple navigation based application for EmployeeContactDirectory. I am displaying the list of Employee. For showing the list of employee, I am using the restfull webservice. I am getting proper response as I want. I have a utility class for Employee Data, class is EmployeeData.h and Employee.m (contains employeeId , employeeFirstName, employeeLastName). My code for parsing
// Code for parsing the response and getting desired field into the dictionary object and add the dictionaries into the array.
-(void)finishedReceivingData:(NSData *)data {
NSData *dataRes = [[restConnection stringData] dataUsingEncoding:NSUTF8StringEncoding];
////////////////Parsing with XPathQuery Start//////////////////////
if (dataRes != NULL) {
employeeData = [[EmployeeData alloc] init];
NSString *xPathQuery = [NSString stringWithFormat:#"/*",employeeData.employeeID];
NSArray *arrayWithObjectList = PerformXMLXPathQuery(dataRes, xPathQuery);
for(NSDictionary *childOfObjectList in arrayWithObjectList){
NSArray *arrayOfDataValueObj = (NSArray *)[childOfObjectList objectForKey:#"nodeChildArray"];
for(NSDictionary *childObjListDict in arrayOfDataValueObj){
NSArray *childObjListDataValue = (NSArray *)[childObjListDict objectForKey:#"nodeChildArray"];
for(NSDictionary *childDict in childObjListDataValue){
if([[childDict objectForKey:#"nodeName"] isEqualToString:#"FName" ])
{
employeeData.employeeFirstName = [childDict objectForKey:#"nodeContent"];
}
if([[childDict objectForKey:#"nodeName"] isEqualToString:#"EmpID"])
{
employeeData.employeeID = [childDict objectForKey:#"nodeContent"];
}
}
//employeeFirstNameArray = [NSArray arrayWithObjects:employeeData, nil];
employeeIDArray = [NSArray arrayWithObjects:employeeData, nil];
dictionaryEmployeeFirstName = [NSDictionary dictionaryWithObject:employeeData.employeeFirstName forKey:#"employeeData"];
dictionaryEmployeeID = [NSDictionary dictionaryWithObject:employeeData.employeeID forKey:#"employeeData"];
tempArray = [NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil];
NSLog(#"size of temp %d",[tempArray count]);
}
}
//[employeeData release];
//employeeData = nil;
}
[self.tableviewEmloyeeList reloadData];
//////////////////////////////Parsing with XPathQuery end//////////
}
-(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] autorelease];
}
// Configure the cell..
NSDictionary *dictionaryEmployee = [tempArray objectAtIndex:indexPath.row];
NSArray *firstNameArray = [dictionaryEmployee objectForKey:#"employeeData"];
NSString *cellValue = [firstNameArray objectAtIndex:indexPath.row];
NSLog(#"cellValue %#",cellValue);
cell.textLabel.text = cellValue;
return cell;
}
I am getting the message (Exc_bad_Access) when this line of code comes into the execution flow:
NSDictionary *dictionaryEmployee = [tempArray objectAtIndex:indexPath.row]
The EXC_Bad_Access is at the mail.m file at line nt retVal = UIApplicationMain(argc, argv, nil, nil);
So, Please tell me how can I set the data into the tableview when I am using NSDictionary. When, user clicks on the row of the tableview it will return the id of the selected employee.
Instead of the line
tempArray = [NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil];
try the following,
if( tempArray )
{
[tempArray release];
tempArray = nil;
}
tempArray = [[NSArray arrayWithObjects:dictionaryEmployeeFirstName, dictionaryEmployeeID, nil] retain];
Since it is autoreleased, it might have been out of memory.
you need to implement a tableView delegate method called
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
here you will get the section & row clicked in the table

App crashing when scrolling TableView

My app is crashing when i scroll my TableView. First in my viewDidLoad method a load a dictionary from a file and for this dictionary i enumerate all keys.
- (void)viewDidLoad {
[super viewDidLoad];
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
path = [rootPath stringByAppendingPathComponent:[NSString stringWithFormat:#"currency.archive"]];
banks = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
keys = [banks allKeys];
// set date for last update
dayMonthYear.text = [banks objectForKey:#"Last Updated"];
}
In my cellForRowAtIndexPath i populate cells with data from that dictionary. Anyway when my app starts everything looks fine, first five rows are drawn correctly, but when i start to scroll my app crash. My idea is that the problem is with autoreleased object here, i tried to retain them and after using them to release ,but unsuccessful. DEBUGGER SHOWS THAT MY PROBLEM IS AT LINE WITH BOLD
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSString *CellIdentifier = [NSString stringWithFormat:#"Cell %d_%d",indexPath.section,indexPath.row];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"CurrencyTableCell" owner:self options:nil];
cell = currencyTableCell;
//don't show selected cell
cell.selectionStyle = UITableViewCellSelectionStyleNone;
//set height
self.cellHeight = cell.frame.size.height;
}
// Fetch currency
NSString *currentCurrency = [keys objectAtIndex:indexPath.row];
NSDictionary *fetchedCurrency = [banks objectForKey:currentCurrency];
**NSString *name = [fetchedCurrency objectForKey:#"Currency Name"];**
currencyTitle.text = name;
NSString *charCode = [fetchedCurrency objectForKey:#"Code"];
currencyCode.text = charCode;
NSString* formattedNumber = [NSString stringWithFormat:#"%.02f",[[fetchedCurrency objectForKey:#"Value"] floatValue]];
if ([formattedNumber length] == 4) {
formattedNumber = [NSString stringWithFormat:#"%#%#",#"0",formattedNumber];
}
buyPrice.text = formattedNumber;
return cell;
}
As a result from the discussion, [banks objectForKey:#"Last Updated"] gives you a NSString, not a NSDictionary!
You could get around this error by doing
if ([[banks objectForKey:currentCurrency] class] == [NSDictionary class]) {
... rest of the code here ..
}
Change your viewDidLoad with below code it will work
- (void)viewDidLoad {
[super viewDidLoad];
NSString *rootPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];
path = [rootPath stringByAppendingPathComponent:[NSString stringWithFormat:#"currency.archive"]];
banks = [[NSDictionary alloc] initWithDictionary:[NSKeyedUnarchiver unarchiveObjectWithFile:path]];
keys = [[NSArray alloc] initWithArray:[banks allKeys]];
// set date for last update
dayMonthYear.text = [banks objectForKey:#"Last Updated"];
}
-[NSCFString objectForKey:]: unrecognized selector sent to instance
0x4bab9c0
Your banks and keys variables aren't retained, as mentioned in another answer, but this isn't the error.
As per this error, your fetchedCurrency object is an NSString, not an NSDictionary. Check the format of your currency.archive file.

retrieved data from sqlite database and displaying it on grouped table view

hii every one
i am brand new to obj c, i have did a sample project where i have 2 screens on the first screen i have six text fields & 2 buttons named save and ViewData ,on click of save data which is entere d in the text field will be get saved in the sqliteData Base ,& on click of the button ViewData it will navigate to a new screen which has a grouped table view, here i am trying to display the data which is stored in the sqlite ,in the grouped table view i have 6 sections i am using following code to display the data in grouped table view,problem is grouped table view is displaing only the last data which is entered ih the text field,,but i need to display all the data which enterd should be shown under that section
appDelegate = (iICS_testAppDelegate *)[[UIApplication sharedApplication] delegate];
for(int intVar=0;intVar < [appDelegate.arrObjects count];intVar++)
{
insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:intVar];
NSLog(#"InsertRecord:%#",InsertRecord);
NSMutableArray *arrTemp1 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strsixth,nil];
NSMutableArray *arrTemp2 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strfifth,nil];
NSMutableArray *arrTemp3 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strFourth,nil];
NSMutableArray *arrTemp4 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strLogin,nil];
NSMutableArray *arrTemp5 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strMiddleName,nil];
NSMutableArray *arrTemp6 = [[NSMutableArray alloc]initWithObjects:InsertRecord.strFirstName,nil];
NSMutableDictionary *temp =[[NSMutableDictionary alloc]initWithObjectsAndKeys:arrTemp1,#"Item Name",arrTemp2,#"Manufacturer",arrTemp3,#"Weight of Item",arrTemp4,#"Num of Item",arrTemp5,#"Price of Item",arrTemp6,#"MFG Date",nil];
self.tableContents =temp;
[temp release];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys =[[self.tableContents allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted %#",self.sortedKeys);
[arrTemp1 release];
[arrTemp2 release];
[arrTemp3 release];
[arrTemp4 release];
[arrTemp5 release];
[arrTemp6 release];
}
here im assigning the text for the row
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:indexPath.row];
static NSString *SimpleTableIdentifier = #"SimpleTableIdentifier";
NSArray *listData =[self.tableContents objectForKey:[self.sortedKeys objectAtIndex:[indexPath section]]];
UITableViewCell * cell = [tableView
dequeueReusableCellWithIdentifier:SimpleTableIdentifier];
if (cell == nil)
{
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:SimpleTableIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
//cell.textLabel.text = [appDelegate.arrObjects objectAtIndex:row];
cell.textLabel.text = [listData objectAtIndex:row];
return cell;
}
thanks in advance!
This is my snapshopt of grouped table view. I need the data which is entered through the text field shoul be viewed under particular section
Solution for only the last data is displaying,
Instead of NSArray use NSMutableArray.
Solution for wrong field values,
Your problem may be in insertion itself,
NSArray *arrTemp1 = [[NSArray alloc]initWithObjects:InsertRecord.strsixth,nil];
NSArray *arrTemp2 = [[NSArray alloc]initWithObjects:InsertRecord.strfifth,nil];
You are inserting price value into date field, i think so. Please check that.
Change your code as,
NSMutableArray *arrTemp1 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp2 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp3 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp4 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp5 = [[NSMutableArray alloc]init];
NSMutableArray *arrTemp6 = [[NSMutableArray alloc]init];
for(int intVar=0;intVar < [appDelegate.arrObjects count];intVar++)
{
insertUpdateDelete *InsertRecord = [appDelegate.arrObjects objectAtIndex:intVar];
NSLog(#"InsertRecord:%#",InsertRecord);
[arrTemp1 addObject:InsertRecord.strsixth];
[arrTemp2 addObject:InsertRecord.strfifth];
[arrTemp3 addObject:InsertRecord.strFourth];
[arrTemp4 addObject:InsertRecord.strLogin];
[arrTemp5 addObject:InsertRecord.strMiddleName];
[arrTemp6 addObject:InsertRecord.strMiddleName];
}
NSDictionary *temp =[[NSDictionary alloc]initWithObjectsAndKeys:arrTemp1,#"Item Name",arrTemp2,#"Manufacturer",arrTemp3,#"Weight of Item",arrTemp4,#"Num of Item",arrTemp5,#"Price of Item",arrTemp6,#"MFG Date",nil];
self.tableContents =temp;
[temp release];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys =[[self.tableContents allKeys] sortedArrayUsingSelector:#selector(compare:)];
NSLog(#"sorted %#",self.sortedKeys);
[arrTemp1 release];
[arrTemp2 release];
[arrTemp3 release];
[arrTemp4 release];
[arrTemp5 release];
[arrTemp6 release];

Help w/ array of dictionaries in a tableview

This is kinda confusing so please bear with me.
I have an array (listOfStates) of dictionaries. Where listOfStates has this structure:
{stateName} - {stateCapital}
{Alabama} - {Montgomery}
{Alaska} - {Juneau}
{Arizona} - {Phoenix}
...
{West Virginia} - {Charleston}
{Wisconsin} - {Madison}
{Wyoming} - {Cheyenne}
This is the code used to obtain the 1st letter of each US State(stateName) in order to group them together alphabetically:
listOfStates = [[NSArray alloc] init];
stateIndex = [[NSMutableArray alloc] init];
NSMutableArray *tempArray = [[NSMutableArray alloc] init];
for (NSDictionary *row in listOfStates) {
[tempArray addObject:[row valueForKey:#"stateName"]];
for (int i=0; i<[tempArray count]-1; i++){
char alphabet = [[tempArray objectAtIndex:i] characterAtIndex:0];
NSString *uniChar = [NSString stringWithFormat:#"%C", alphabet];
if (![stateIndex containsObject:uniChar]){
[stateIndex addObject:uniChar];
}
}
}
That code works beautifully, however I'm having issues understanding how to populate a tableview cell with BOTH the #"stateName" and #"stateCapital"(as the subtitle) after I use NSPredicate to sort the array.
-(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] autorelease];
}
//---get the letter in the current section---
NSString *alphabet = [stateIndex objectAtIndex:[indexPath section]];
//---get all states beginning with the letter---
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"SELF beginswith[c] %#", alphabet];
NSArray *states = [[listOfStates valueForKey:#"stateName"] filteredArrayUsingPredicate:predicate];
//---extract the relevant state from the states object---
cell.textLabel.text = [states objectAtIndex:indexPath.row];
//cell.textLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateName"];
//cell.detailTextLabel.text = [[listOfStates objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
return cell;
}
Any help is appreciated and I am more than willing to send the entire project, if you think it'll help you understand.
Thank you so much.
cell.textLabel.text = [[states objectAtIndex:indexPath.row] objectForKey:#"stateName"];
cell.detailTextLabel.text =[states objectAtIndex:indexPath.row] objectForKey:#"stateCapital"];
Update:
Unfortunately, the 'states' array only
includes the state names...
Change the predicate and filter to:
NSPredicate *p=[NSPredicate predicateWithFormat:#"stateName beginswith[c] %#", alphabet];
NSArray *states=[listOfStates filteredArrayUsingPredicate:p];
...that will give you an array of states that all start with the same letter. Then you can sort the array and the row will give you the right state dictionary.
Maybe change the data structure so you have one dictionary with state name as a key and state capital as a value. That way you can sort your keys and get the value using the keys, not indexes.