Ordering UITableView Sections Loaded From pList - iphone

I have a sectioned UITableView being populated by data from a pList. The root of the pList is a dictionary, each key of this dictionary is loaded into an array, which is used to define the section headings (and presumably order).
Currently my sections appear in the table in a random order, I would like to order them as they appear in the pList, or at least fake it by ordering the sections alphabetically.
I understand that dictionaries have no order, which is why the output does not reflect the pList order, but I would prefer not to change the root to an array as it requires me to rewrite chunks of my app, plus Xcode 4 seems to prefer you using a dictionary as the root. Of course if changing the pList structure is the best method, I'll go with that.
pList sample:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>Section A</key>
<array>
<dict>
<key>Details</key>
<string>Details Here...</string>
<key>Image</key>
<string>X.png</string>
<key>Name</key>
<string>Person X</string>
</dict>
<dict>
<key>Details</key>
<string>Details Here...</string>
<key>Image</key>
<string>Y.png</string>
<key>Name</key>
<string>Person Y</string>
</dict>
</array>
<key>Section B</key>
<array>
<dict>
<key>Details</key>
<string>Details Here...</string>
<key>Image</key>
<string>Z.png</string>
<key>Name</key>
<string>Person Z</string>
</dict>
</array>
</dict>
Code within 'TableViewController.m':
- (void)viewDidLoad {
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle] pathForResource:#"Team" ofType:#"plist"];
NSDictionary *tempDict = [[NSDictionary alloc] initWithContentsOfFile:path];
self.teamDictionary = tempDict;
[tempDict release];
NSArray *tempArray = [[NSArray alloc] init];
self.teamArray = tempArray;
[tempArray release];
self.teamArray = [self.teamDictionary allKeys];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [self.teamArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [[self.teamDictionary valueForKey:[self.teamArray objectAtIndex:section]] count];
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
// this is here because I am altering the appearance of the header text
UIView* customView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, tableView.bounds.size.width, 44.0)] autorelease];
UILabel * headerLabel = [[UILabel alloc] initWithFrame:CGRectZero];
// some custom formatting stuff has been removed from here...
headerLabel.text = [self.teamArray objectAtIndex:section];
[customView addSubview:headerLabel];
[headerLabel release];
return customView;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [teamArray objectAtIndex:section];
NSArray *teamMember = [teamDictionary objectForKey:key];
static NSString *SectionsTableIdentifier = #"SectionsTableIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:SectionsTableIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:SectionsTableIdentifier] autorelease];
}
// Configure the cell...
NSDictionary *name = [teamMember objectAtIndex:row];
cell.textLabel.text = [name objectForKey:#"Name"];
}

I can think of two options:
Use an array as the root of your plist. Each item in the array would be a dictionary, with two keys: name/title and items. Name/title would be a string and items would be an array.
Keep your plist as is, order the keys alphabetically:
NSArray *sortedKeys = [[dict allkeys] sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)]];

Related

Plist to UITableView

I am trying to populate a UITableView with information from a plist file. I don't know where I am going wrong. Please check the images for my requirement and the code above to find where I am wrong
I need to populate above image in UITableView in such way that array a, b, c should come in the section field. Its coming right in below. But I am unable to populate data
please check where I am wrong.
.
.
#synthesize mySections //array
#synthesize myData //dictionary
- (void)viewDidLoad
{
[super viewDidLoad];
//LOADING THE PLIST FILE
//Create a string representing the file path
NSString *plistPath = [bundle pathForResource:#"yourFilename" ofType:#"plist"];
//Load the file in a dictionnary
NSDictionary *dict = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
self.myData = dict;
//SORTING THE DICTIONARY
NSArray *dicoArray = [[self.myData allKeys] sortedArrayUsingComparator:^(id firstObject, id secondObject) {
return [((NSString *)firstObject) compare:((NSString *)secondObject) options: NSCaseInsensitiveSearch];
}];
self.mySections = dicoArray;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
//Return the number of sections.
return [self.mySections count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
NSString *key = [self.mySections objectAtIndex:section];
NSArray *dataInSection = [self.myData objectForKey:key];
return [dataInSection count];
}
-(NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSString *key = [self.mySections objectAtIndex:section];
return [NSString stringWithFormat:#"%#", key];
}
-(NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return self.mySections;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell...
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [self.mySections objectAtIndex:section];
NSDictionary *Dic=self.myData;
NSArray *dataForSection = [self.myData objectForKey:Dic.allKeys];
cell.textLabel.text = [dataForSection objectAtIndex:row];
return cell;
}
some code of plist is:-
<plist version="1.0">
<dict>
<key>a</key>
<array>
<dict>
<key>Beta_Carot_(µg)</key>
<string>0.06</string>
<key>Cholestrl_(mg)</key>
<string>215</string>
<key>fdgdfg</key>
<string>dfgdfg</string>
</dict>
</array>
<key>b</key>
<array>
<dict>
<key>Alpha_Carot_(µg)</key>
<string>0</string>
<key>gdfg</key>
<string>fdgdfg</string>
</dict>
</array>
<key>c</key>
<array>
<dict>
<key>Alpha_Carot_(µg)</key>
<string>0</string>
<key>Ash_(g)</key>
<string>0</string>
<key>Beta_Caro</key>
<string>193</string>
<key>Choline_Tot_ (mg)</key>
<string>22.3</string>
<key>dgd</key>
<string>dgdf</string>
</dict>
</array>
</dict>
</plist>
You need to get to count the number of elements in the right data structure when determining the number of rows in each section. So in - tableView: numberOfRowsInSection: you need to have
NSArray *dataInSection = [[self.myData objectForKey:key] objectAtIndex:0];
return [dataInSection count];
There is also a problem in - tableView: cellForRowAtIndexPath:. You create the correct key to get the data for your section in *key but then you instead use Dic.allKeys as a key to retrieve data from self.myData. So you are sending in a whole array as the key when you set *dataForSection.
So change these lines:
NSString *key = [self.mySections objectAtIndex:section];
NSDictionary *Dic=self.myData;
NSArray *dataForSection = [self.myData objectForKey:Dic.allKeys];
cell.textLabel.text = [dataForSection objectAtIndex:row];
To:
NSString *key = [self.mySections objectAtIndex:section];
NSDictionary *dataForSection = [[self.myData objectForKey:key] objectAtIndex:0];
cell.textLabel.text = [[dataForSection allKeys] objectAtIndex:row];
I think you're not drilling far enough down your data hierarchy. In numberOfRowsInSection: you're getting the value for the key in the root level dictionary: Looks like this is always an NSArray with only a single item: A dictionary. You probably want something like
...
NSDictionary *dataInSection = [[self.myData objectForKey:key] objectAtIndex:0];
return [dataInSection count];
...
According to me you are doing some mistake in table fetch data from plist
plz try this
- (void)viewDidLoad
{
[super viewDidLoad];
//LOADING THE PLIST FILE
//Create a string representing the file path
NSString *plistPath = [bundle pathForResource:#"yourFilename" ofType:#"plist"];
NSMutableArray *listArray=[NSMutableArray arrayWithContentsOfFile:[[NSBundle mainBundle] pathForResource:#"yourFilename" ofType:#"plist"]];
self.sections = [[NSMutableDictionary alloc] init];
}
Then set your data according to your need from plist data come as an array, then dict may be help this information you..

TableView not populating after first drilldown

I have a Sectioned Tableview sourced from a pList which I want to drill down into children sub views. My only problem is I'm stuck on getting it to populate after first drill down (Entree is the only one with content), "Description" and "Title".
pList
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Rows</key>
<array>
<dict>
<key>Title</key>
<string>Entree</string>
<key>Children</key>
<array>
<dict>
<key>Title</key>
<string>Garlic Bread</string>
<key>Description</key>
<string>Cottage loaf smeared with garlic butter and herbs</string>
<key>Price</key>
<string>8.0</string>
</dict>
<dict>
<key>Title</key>
<string>Bruschetta</string>
<key>Description</key>
<string>Veggies n shit on toast</string>
<key>Price</key>
<string>9.0</string>
</dict>
</array>
</dict>
<dict>
<key>Title</key>
<string>Mains</string>
</dict>
<dict>
<key>Title</key>
<string>Dessert</string>
</dict>
<dict>
<key>Title</key>
<string>Sides</string>
</dict>
</array>
<key>Title</key>
<string>Eat</string>
</dict>
<dict>
<key>Title</key>
<string>Drink</string>
<key>Rows</key>
<array>
<dict>
<key>Title</key>
<string>Red</string>
</dict>
</array>
</dict>
</array>
</plist>
MenuViewController.h
#import <UIKit/UIKit.h>
#interface MenuViewController : UITableViewController {
NSArray *tableDataSource;
NSString *CurrentTitle;
NSInteger CurrentLevel;
}
#property (nonatomic, retain) NSArray *tableDataSource;
#property (nonatomic, retain) NSString *CurrentTitle;
#property (nonatomic, readwrite) NSInteger CurrentLevel;
#end
MenuViewController.m
#import "MenuViewController.h"
#implementation MenuViewController
#synthesize tableDataSource;
#synthesize CurrentLevel, CurrentTitle;
- (void)viewDidLoad
{
[super viewDidLoad];
if(CurrentLevel == 0) {
self.tableDataSource = [NSArray arrayWithContentsOfFile: [[NSBundle mainBundle] pathForResource: #"MenuData" ofType: #"plist"]];
self.navigationItem.title = #"Menu";
}
else
self.navigationItem.title = CurrentTitle;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
#warning Potentially incomplete method implementation.
return [tableDataSource count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
#warning Incomplete method implementation.
return [[[tableDataSource objectAtIndex: section]
objectForKey: #"Rows"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[tableDataSource objectAtIndex: section]
objectForKey: #"Title"];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *dictionary = [[[self.tableDataSource objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
*//The problem is right here, im just stuck on how to access this property correctly
**cell.textLabel.text = [dictionary objectForKey:#"Title"];***
// Configure the cell...
return cell;
}
/*
// Override to support conditional editing of the table view.
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the specified item to be editable.
return YES;
}
*/
/*
// Override to support conditional rearranging of the table view.
- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
// Return NO if you do not want the item to be re-orderable.
return YES;
}
*/
#pragma mark - Table view delegate
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
// Navigation logic may go here. Create and push another view controller.
/*
<#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:#"<#Nib name#>" bundle:nil];
// ...
// Pass the selected object to the new view controller.
[self.navigationController pushViewController:detailViewController animated:YES];
[detailViewController release];
*/
NSDictionary *dictionary = [[[self.tableDataSource objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row];
//Get the children of the present item.
NSArray *Children = [dictionary objectForKey:#"Children"];
if([Children count] == 0) {
MenuDetailViewController *mdvController = [[MenuDetailViewController alloc] initWithNibName:#"MenuDetailView" bundle:[NSBundle mainBundle]];
[self.navigationController pushViewController:mdvController animated:YES];
[mdvController release];
}
else {
//Prepare to tableview.
MenuViewController *mvController = [[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:[NSBundle mainBundle]];
//Increment the Current View
mvController.CurrentLevel += 1;
//Set the title;
mvController.CurrentTitle = [dictionary objectForKey:#"Title"];
//Push the new table view on the stack
[self.navigationController pushViewController:mvController animated:YES];
mvController.tableDataSource = Children;
[mvController release];
}
}
#end
You can drill data in recursive manner.
For root view controller cell selection method
you have to modify your code as
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
if(self.currentLevel=0)
return [tableDataSource count];
else
return 1;//You require only one section in later levels
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
if(self.currentLevel=0)
return [[[tableDataSource objectAtIndex: section] objectForKey: #"Rows"] count];
else
return [tableDataSource count];// Number of children
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
if(self.currentLevel=0)
return [[tableDataSource objectAtIndex: section] objectForKey: #"Title"];
else
return self.title;//Or your custom title
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
NSDictionary *dictionary = nil;
if(self.currentLevel=0)
dictionary= [[[self.tableDataSource objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row];
else
dictionary = [self.tableDataSource objectAtIndex: indexPath.row];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
cell.textLabel.text = [dictionary objectForKey:#"Title"];
// Configure the cell...
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
if(self.currentLevel=0)
dictionary= [[[self.tableDataSource objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row];
else
dictionary = [self.tableDataSource objectAtIndex: indexPath.row];
if([dictionary objectForKey:#"Children"]!=nil){
//Drill down only if you have child
//Now drilling down logic
id Object = [dictionary objectForKey:#"Children"];
NSString * title = [dictionary objectForKey:#"Title"];
if([object isKindOfClass:[NSArray class]) {
NSArray * dataSource = (NSArray *)object;
MenuViewController * viewController = [[MenuViewController alloc] initWithNibName:#"YourNibName" bundleNameOrNil:nil];
viewController.title = title;
viewController.tableDataSource = dataSource;
viewController.currentLevel = self.currentLevel+1;
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
} else if([object isKindOfClass:[NSDictionary class]) {
//Only one child in the form of dictionary
//Initialize your detail view controller and push to nav stack
YourDetailViewController * viewController = [[YourDetailViewController alloc] initWithNibName:#"YourNibName" bundleNameOrNil:nil];
viewController.data = (NSDictionary*)object;//Pass the view data(price etc)
viewController.currentLevel = self.currentLevel+1;
[self.navigationController pushViewController:viewController animated:YES];
[viewController release];
} else {
//Error drilling down is not possible
}
}
}
Hope this will sort out your drilling problem.. :)

Sorted UITableViewCell by plist (not name of textLabel)

All new code, I have no idea why this doesn't work. It loads the table with all my data, not just in order of alphabetical state...
UPDATE: Data Structure added:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Rows</key>
<array>
<dict>
<key>Subtree</key>
<array>
<string>Address</string>
<string>Tuesday</string>
<string>Information</string>
<integer>36</integer>
<integer>-118</integer>
<string>Place LA</string>
<string>California</string>
</array>
<key>Title</key>
<string>California</string>
</dict>
<dict>
<key>Subtree</key>
<array>
<string>Address</string>
<string>Sunday</string>
<string>Information</string>
<integer>40</integer>
<integer>-72</integer>
<string>NY Place</string>
<string>New York</string>
</array>
<key>Title</key>
<string>New York</string>
</dict>
<dict>
<key>Subtree</key>
<array>
<string>Address</string>
<string>Sunday</string>
<string>Information</string>
<integer>30</integer>
<integer>-97</integer>
<string>Austin Place</string>
<string>Texas</string>
</array>
<key>Title</key>
<string>Texas</string>
</dict>
<dict>
<key>Subtree</key>
<array>
<string>Address</string>
<string>Wednesday</string>
<string>Information</string>
<integer>30</integer>
<integer>-97</integer>
<string>Cleveland Place</string>
<string>Ohio</string>
</array>
<key>Title</key>
<string>Ohio</string>
</dict>
</array>
</dict>
</array>
</plist>
- (void)viewDidLoad {
[super viewDidLoad];
if (!self.tableData)
{
[self sortedArray];
self.title = #"Title"
}
}
-(NSArray *)sortedArray
{
NSString *path = [[NSBundle
mainBundle]pathForResource:#"Data3" ofType:#"plist"];
tableData = [NSArray arrayWithContentsOfFile:path];
NSArray *rows = [[tableData objectAtIndex:0]objectForKey:#"Rows"];
NSArray *rows2 = [[rows objectAtIndex:0]objectForKey:#"Subtree"];
NSString *states = [NSString stringWithFormat:#"%#",[rows2 objectAtIndex:6]];
NSString *days = [NSString stringWithFormat:#"%#",[rows2 objectAtIndex:1]];
NSSortDescriptor *stateDescriptor = [[NSSortDescriptor alloc]initWithKey:states ascending:YES];
NSSortDescriptor *dayDescriptor = [[NSSortDescriptor alloc]initWithKey:days ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:stateDescriptor, dayDescriptor, nil];
NSArray *finalArray = [tableData sortedArrayUsingDescriptors:sortDescriptors];
return finalArray;
}
- (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];
}
cell.textLabel.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:24];
cell.textLabel.text = [[[[tableData objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row] objectForKey: #"Title"];
cell.detailTextLabel.font = [UIFont fontWithName:#"MarkerFelt-Thin" size:14];
cell.detailTextLabel.text = [[[[[tableData objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row] objectForKey: #"Subtree"]objectAtIndex:0];
return cell;
}
In view did load, maybe
self.tableDate = [self sortedArray];
In your sortedArray method, you're sorting the data and returning it, but never assigning the sorted array to anything.
You are assigning the unsorted data to tableData in the sortedArray method though, which is why you get the unsorted data. I'd take that assignment out, it's confusing.

Configuring a UITableViewCell object with unique image and text

Given a .plist similar to :
<plist version="1.0">
<array>
<dict>
<key>name</key>
<string>Afghanistan</string>
<key>government</key>
<string>Islamic Republic</string>
<key>population</key>
<integer>0</integer>
<key>image</key>
<string>/Flags/afghanistan.png</string>
</dict>
<dict>
<key>name</key>
<string>Albania</string>
<key>government</key>
<string>Emerging Democracy</string>
<key>population</key>
<integer>0</integer>
<key>image</key>
<string>/Flags/albania.png</string>
</dict>
.... etc.
And ViewController.m :
#import "FirstViewController.h"
#implementation FirstViewController
#synthesize sortedCountries;
-(void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"countries" ofType:#"plist"];
NSArray *countries = [NSArray arrayWithContentsOfFile:path];
NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES] autorelease];
self.sortedCountries = [countries sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
}
-(UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary *country = [sortedCountries objectAtIndex:indexPath.row];
NSString *countryName = [country objectForKey:#"name"];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell =
[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier] autorelease];
}
NSDictionary *item = (NSDictionary *)[sortedCountries objectAtIndex:indexPath.row];
NSString *path = [[NSBundle mainBundle] pathForResource:[item objectForKey:#"image"] ofType:#"png"];
UIImage *theImage = [UIImage imageWithContentsOfFile:path];
cell.imageView.image = theImage;
cell.textLabel.text = countryName;
return cell;
}
This puts countryName in ascending alphabetical order as expeted in the UITableView Cells. What is not working is cell.imageView.image.
It puts afghanistan.png in the first UITableViewCell as expected. The Cells that follow also receive afghanistan.png as well however. ( The second cell should receive 'albania.png', etc ). How can I fix this UIImageView problem?
Use imageNamed instead.
cell.imageView.image = [UIImage imageNamed:[item objectForKey:#"image"]];
You should use
[item objectForKey:#"image"] in stead of
[item objectForKey:#"imageKey"]
(as the .plist uses <key>image</key>).

sectioned UITableView sourced from a pList

I'm having trouble finding a easy to understand tutorial on having a sectioned UITableView which gets its data from a pList file.
Things im having trouble with, is how to properly structure the pList file to cater for 2 different sections.
The root of the plist should be an array. The array should contain two dictionaries (your sections). The dictionaries will contain two keys: one for section title and one for the rows in the section.
Assuming you read your plist into an NSArray* sections, you can return the section, row count, section title and cell titles using the code below.
Your plist file would look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<array>
<dict>
<key>Title</key>
<string>Section1</string>
<key>Rows</key>
<array>
<string>Section1 Item1</string>
<string>Section1 Item2</string>
</array>
</dict>
<dict>
<key>Title</key>
<string>Section2</string>
<key>Rows</key>
<array>
<string>Section2 Item1</string>
<string>Section2 Item2</string>
</array>
</dict>
</array>
</plist>
#import "RootViewController.h"
#interface RootViewController ()
#property (copy, nonatomic) NSArray* tableData;
#end
#implementation RootViewController
#synthesize tableData;
- (void) dealloc
{
self.tableData = nil;
[super dealloc];
}
- (void) viewDidLoad
{
[super viewDidLoad];
self.tableData = [NSArray arrayWithContentsOfFile: [[NSBundle mainBundle] pathForResource: #"Table" ofType: #"plist"]];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView;
{
return [tableData count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section;
{
return [[[tableData objectAtIndex: section] objectForKey: #"Rows"] count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section;
{
return [[tableData objectAtIndex: section] objectForKey: #"Title"];
}
- (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];
}
cell.textLabel.text = [[[tableData objectAtIndex: indexPath.section] objectForKey: #"Rows"] objectAtIndex: indexPath.row];
return cell;
}
#end