Having issue with reading Plist into UITableView - iphone

I am trying to display a dictionary plist into UITableView , I have read many question and answer here but no luck ! it seems cells return null ! here is my plist :
and my codes :
-(void)viewDidLoad {
NSString *path = [[NSBundle mainBundle] pathForResource:#"feed" ofType:#"plist"];
newsFeed = [NSArray arrayWithContentsOfFile:path];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return newsFeed.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dictionary.allKeys.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dictionary = [newsFeed objectAtIndex:indexPath.section];
cell.textLabel.text = [[newsFeed objectAtIndex:indexPath.row] valueForKey:#"title"];
return cell;
}
and the result is nothing :

Try this in you want to display only title then try this
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return newsFeed.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dictionary = [newsFeed objectAtIndex:indexPath.row];
cell.textLabel.text = [dictionary valueForKey:#"title"];
return cell;
}
EDIT
And if you want to display all record then try this
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return newsFeed.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return dictionary.allKeys.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dictionary = [newsFeed objectAtIndex:indexPath.section];
NSString *key =[[dictionary allKeys] objectAtIndex:indexPath.row];
cell.textLabel.text = [dictionary valueForKey:key];
return cell;
}

You should learn how to debug problems like this. Or if you tried, you should tell us what you tried in the question.
Set a breakpoint in viewDidLoad and make sure, the plist is loaded correctly. The path might be wrong. The file might be corrupt or have a different root object then what you're expecting.
Set a breakpoint in numberOfSectionsInTableView. Is it called at all? Is it called before or after you load your plist? Probably after. In that case you need to call [tableView reloadData]. If it's called what do you return.
Continue like this, step for step until you find the reason.

Try this,I use plist's a lot.
In ViewDidLoad
NSString *plistPath = [[[NSBundle mainBundle] bundlePath] stringByAppendingPathComponent:self.plistName];
self.tableContents=[NSDictionary dictionaryWithContentsOfFile:plistPath];
NSLog(#"table %#",self.tableContents);
NSLog(#"table with Keys %#",[self.tableContents allKeys]);
self.sortedKeys = [[self.tableContents allKeys] sortedArrayUsingSelector:#selector(localizedStandardCompare:)];
- (NSInteger)tableView:(UITableView *)table numberOfRowsInSection:(NSInteger)section {
NSArray *listData =[self.tableContents objectForKey:[self.sortedKeys objectAtIndex:section]];
return [listData count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
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];
}
cell.selectionStyle=UITableViewCellSelectionStyleNone;
NSUInteger row = [indexPath row];
cell.textLabel.text = [NSString stringWithFormat:#" %#",[listData objectAtIndex:row]]; //take your object out
return cell;
}

Set the Root As NSDictionary, put your newsFeed in the dictionary.
Use NSDictionary *dict = [NSDictionary ...fromFile:...];
newsFeed = [dict valueForKey:#"some_key"];

Related

Display Plist into UITableview

I want to display Plist to the UITableView .By my below code I can display one key values that is list of states. but i want to display all the values of three tables.
- (id)readPlist:(NSString *)fileName
{
NSData *plistData;
NSString *error;
NSPropertyListFormat format;
id plist;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:fileName ofType:#"plist"];
plistData = [NSData dataWithContentsOfFile:localizedPath];
plist = [NSPropertyListSerialization propertyListFromData:plistData mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
if (!plist) {
NSLog(#"Error reading plist from file '%s', error = '%s'", [localizedPath UTF8String], [error UTF8String]);
}
return plist;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
return [[[self readPlist:#"sample"] objectForKey:#"ListOfStates"] 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] autorelease];
}
cell.textLabel.text = [[[self readPlist:#"sample"] objectForKey:#"ListOfStates"] objectAtIndex:indexPath.row];
return cell;}
MY output comes only listofkeystates values
is it also possible to display key name with values
Maybe use table sections...
-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView {
NSDictionary* dict = [self readPlist:#"sample"];
return dict.allKeys.count;
}
-(NSString*) tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
NSDictionary* dict = [self readPlist:#"sample"];
return [dict.allKeys objectAtIndex:section];
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
NSDictionary* dict = [self readPlist:#"sample"];
NSString* key = [dict.allKeys objectAtIndex:section];
return [[dict valueForKey:key] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSDictionary* dict = [self readPlist:#"sample"];
NSString* key = [dict.allKeys objectAtIndex:indexPath.section];
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
cell.textLabel.text = [[dict objectForKey:key] objectAtIndex:indexPath.row];
return cell;
}
just try to get data in NSDictionary and NSArray and then use it in UITableView
NSString *file = [[NSBundle mainBundle] pathForResource:#"sample" ofType:#"plist"];
NSDictionary *dict = [NSDictionary dictionaryWithContentsOfFile:file];
and use tableValue with its name like bellow...
NSArray *array = [dict objectForKey:#"ListOfStates"];
NSLog(#"%#", array);
i hope this help you..
EDIT : Corrected some typo mistakes
The idea
Loading plist in a dictonary
optional : sort it (!)
create the array of data for each section
create the array of section
Then implement the following things
viewDid load -> load the plist file in a dictionary, create an array of the sections and a dictionary of the data
numberOfSectionsInTableView -> the number of sections. In your case the number of keys
numberOfRowsInSection -> the number of rows of each section
titleForHeaderInSection -> for each section, the title of the section
cellForRowAtIndexPath -> the data of all row
sectionIndexTitlesForTableView -> the array that holds all you sections names. In your case all the keys
assuming you have a property called mySections and a property called myData
also assuming you use storyboard with standard cell with recycle identifier "Cell"
#synthesize mySections
#synthesize myData
- (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
{
NSUInteger section = [indexPath section];
NSUInteger row = [indexPath row];
NSString *key = [self.mySections objectAtIndex:section];
NSArray *dataForSection = [self.myData objectForKey:key];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"Cell" forIndexPath:indexPath];
cell.textLabel.text = [dataForSection objectAtIndex:row];
return cell;
}

How to implement Alphabetical section headers in a UITableView having content getting from DataBase

Till now I have implemented UITableView by populate the contents from the database
By retrieving in an array from sqlite data base
storedContactsArray = [Sqlitefile selectAllContactsFromDB];
so no multiple sections , section headers and returns storedContactsArray.count as number of rows.
Now i need to populate the same data in table view but The data set in Alpabetical sections in alphabetical order.
I tried with
alphabetsArray =[[NSMutableArray 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];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [alphabetsArray count];
}
- (NSArray *)sectionIndexTitlesForTableView:(UITableView *)tableView {
return alphabetsArray;
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [alphabetsArray objectAtIndex:section];
}
But in case of numberOfRowsInSection it fails since there is no contacts in storedContactsArray initially
Error occurs: -[__NSArrayM objectAtIndex:]: index 25 beyond bounds for empty array
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[storedContactsArray objectAtIndex:section] count]
}
any advice of use full links pls
To achieve your requirement you need to first separate out all the data in to section as Alphabetical order. which is as following.
Here section is a Mutable Dictionary in which we will get all data as alphabetical sets.
//Inside ViewDidLoad Method
sections = [[NSMutableDictionary alloc] init]; ///Global Object
BOOL found;
for (NSString *temp in arrayYourData)
{
NSString *c = [temp substringToIndex:1];
found = NO;
for (NSString *str in [sections allKeys])
{
if ([str isEqualToString:c])
{
found = YES;
}
}
if (!found)
{
[sections setValue:[[NSMutableArray alloc] init] forKey:c];
}
}
for (NSString *temp in arrayYourData)
{
[[sections objectForKey:[temp substringToIndex:1]] addObject:temp];
}
-(NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [[sections allKeys]count];
}
-(NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[sections valueForKey:[[[sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] 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];
}
NSString *titleText = [[sections valueForKey:[[[sections allKeys] sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)] objectAtIndex:indexPath.section]] objectAtIndex:indexPath.row];
cell.textLabel.text = titleText;
return cell;
}
Please try it I am using it and it working fine
Hope it helps you !!!

Data from Plist is Incorrectly Ordered in UITableView

I have data that is stored in a plist but when I pull it to my UITableView it gets reordered for some reason. Here are my table view data source methods:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.lunch_Dinner count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
return [[self.lunch_Dinner allKeys] objectAtIndex:section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSString *typeOfEntree = [self tableView:tableView titleForHeaderInSection:section];
return [[self.lunch_Dinner valueForKey:typeOfEntree] count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"EntreeCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell...
NSString *typeOfEntree = [self tableView:tableView titleForHeaderInSection:indexPath.section];
NSString *entree = [[self.lunch_Dinner valueForKey:typeOfEntree] objectAtIndex:indexPath.row];
cell.textLabel.text = entree;
return cell;
}
Here is the order of the plist:
Appetizers
Soups
Pastas
Pizzas
Specials
And this is the resulting order in the UITableView after being compiled:
Pizzas
Soups
Appetizers
Pastas
Specials
Any help would be great!
Thanks in advance.
If you want to store table in plist it is better to consider the following structure:
NSArray *sections = [NSArray arrayWithObjects:
[NSDictionary dictionaryWithObject:
[NSArray arrayWithObjects:row_1, row_2, ... , nil]
forKey:#"section name 1"],
[NSDictionary dictionaryWithObject:
[NSArray arrayWithObjects:row_1, row_2, ... , nil]
forKey:#"section name 2"],
...
[NSDictionary dictionaryWithObject:
[NSArray arrayWithObjects:row_1, row_2, ... , nil]
forKey:#"section name N"],
nil];
This code representation is easy to reproduce as plist. Create it as in example below
This structure can be easily used as UITableView datasource
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return [self.datasource count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
NSDictionary *dict = [self.datasource objectAtIndex:section];
return [dict.allKeys lastObject];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSDictionary *dict = [self.datasource objectAtIndex:section];
return [dict.allValues.lastObject count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSDictionary *dict = [self.datasource objectAtIndex:indexPath.section];
id cellPresenter = [dict.allValues.lastObject objectAtIndex:indexPath.row];
...
}
It looks like lunch_Dinner is a NSDictionary. NSDictionarys are unordered, so you are not guaranteed a specific output order from them.
It is a little hard to see exactly what value you're getting from having a key/value pair here, but one option would be to keep a separate NSArray with the correct ordering, and use that to correctly populate things.

How to implement sections in table view containing SQLite3 database?

I have an application which display large amount of values using UITableView and imported sqlite3 database. Now i face problem that i need to make sections for elements. It must be similar for default application "contacts" in iPhone, but i don't want for that section to sort elements only for first letter. Database contains data about food, so sections should be like "Bread", "Meat", "Fish", etc.
Please help, any advice will be appreciated!
Make a NSDictionary whose key is title to be displayed and value is NSArray which consist of all the objects that contain. Now do the following :
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [[dict allkeys]count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection(NSInteger)section
{
//Number of rows it should expect should be based on the section
NSArray *array = [dict objectForKey:[[dict allKeys] objectAtIndex:section]];
return [array count];
}
- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section {
return [[dict allKeys] objectAtIndex:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];
}
// Set up the cell...
cell.text = [[dict objectForkey:[[dict allKeys] objectAtIndex:indexpath.section]] objectAtIndex:indexPath.row];
return cell;
}

UITableView: use object from dictionary as title on detail view

I have the following code to make a table from string turned into a dictionary:
- (void)viewDidLoad {
[super viewDidLoad];
testArray = [[NSArray alloc] init];
NSString *testString = #"Sam|26,Hannah|22,Adam|30,Carlie|32";
testArray = [testString componentsSeparatedByString:#","];
dict = [NSMutableDictionary dictionary];
for (NSString *s in testArray) {
testArray2 = [s componentsSeparatedByString:#"|"];
[dict setObject:[testArray2 objectAtIndex:1] forKey:[testArray2 objectAtIndex:0]];
}
}
- (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];
}
// Configure the cell.
if (testArray.count >indexPath.row) {
cell.textLabel.text = [[dict allKeys] objectAtIndex:[indexPath row]];
cell.detailTextLabel.text = [dict objectForKey:cell.textLabel.text];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
What I would like is for the selected row title to be set as the title on my detail view.
I tried with:
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
self.detailController.title = [[dict allKeys] objectAtIndex:[indexPath row]];
[self.navigationController pushViewController:self.detailController animated:YES];
}
But I get an "EXC_BAD_ACCESS" error.
It works fine if I use #"1" as title, it's just something with my dictionary call that's wrong, I assume.
Make dict a retained dictionary instead of an autoreleased one.
I.E. declare it maybe like this:
dict = [[NSMutableDictionary alloc] initWithCapacity: [testArray count]];
in your viewDidLoad method. Make sure to release it when viewDidUnload is called.
Also, make sure of the number of keys in your dict before calling:
self.detailController.title = [[dict allKeys] objectAtIndex:[indexPath row]];
So, I would do:
if(dict && ([[dict allKeys] count] > [indexPath row])
{
self.detailController.title =
[[dict allKeys] objectAtIndex:[indexPath row]];
} else {
self.detailController.title = #"Here's a problem";
}
Did you implement these UITableView delegate methods ? All these are needed. Also can you post more detailed StackTrace.
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
return [resultSet count];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (CGFloat)tableView:(UITableView *)tableView
heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
return 280.0;
}