Setting textLabel.text in UITableView using JSON data - ios5

I will preface the question with I am new to iOS and could use a little push. I have been trying to figure this out for a few days and fear I am not able to figure out the solution out of my frustration. It is my hope that some new eyes backed with experience will be able to help me out with this.
I have a JSON file that I want to use for various portions of my application. The file can be viewed at https://raw.github.com/irong8/stronger-nation-data/master/data.json for reference.
I am using Storyboards and want to accomplish this using the built in JSON support of iOS5. I created a new TableViewController subclass and have included the code below.
Here is my .h file
#import <UIKit/UIKit.h>
#interface StateTableViewController : UITableViewController
{
NSArray *StateList;
}
#property (nonatomic, retain) NSArray *StateList;
- (void) buildStateList;
#end
Here is my .m file
#import "StateTableViewController.h"
#implementation StateTableViewController
#synthesize StateList;
- (void)buildStateList {
NSString *jsonFile = [ [NSBundle mainBundle] pathForResource:#"data" ofType:#"json" ];
NSError *jsonError = nil;
NSData *jsonData = [NSData dataWithContentsOfFile:jsonFile options:kNilOptions error:&jsonError ];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&jsonError];
NSArray *jsonArray = [json objectForKey:#"states"];
self.StateList = jsonArray;
}
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self buildStateList];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [StateList 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];
}
cell.textLabel.text = [NSString stringWithFormat:#"%d", indexPath.row];
return cell;
}
I can loop through the StateList array using the following and see the state names I am looking for.
for (NSString *element in StateList) {
NSLog(#"element: %#", element);
}
When I load this view, a TableView is loaded with 50 rows (as expected as there are 50 state records in my data file) and each row is numbered 0-49. I am having trouble figuring out how to access the state name in my StateList array.
Any help along the way would be much appreciated!

You would populate your tableview's cells with data in cellForRow... Here is a slight modification of the default implementation in new projects:
- (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];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
// Configure the cell.
NSInteger rowNumber = indexPath.row;
NSString *stateName = [StateList objectAtIndex:rowNumber];
cell.textLabel.text = stateName;
return cell;
}
EDIT The reason your app is now crashing is the object for the key "states" is a dictionary (as it should be according to the json at the link you posted) and you cannot simply cast it to an array. You can, however, ask the dictionary for an array of all of the keys. Which in this case will be the state names.
Change this line of code in buildStateList:
NSArray *jsonArray = [[json objectForKey:#"states"] allKeys];

Related

TableViewController not showing json data

I'm a beginner and I've read everything on StackOverflow about my problem - my app with json data doesn't show anything on TableViewController. I'm probably missing something obvious, but the help is appreciated very very much. (I'm using the latest Xcode 5 DP, if it's important).
TableVC.h
#interface TableVC : UITableViewController <UITableViewDataSource, UITableViewDelegate>
#property (strong, nonatomic) NSDictionary *kinos;
#property (retain, nonatomic) UITableView *tableView;
-(void)fetchKinos;
#end
And the TableVC.m file is
#interface TableVC ()
#end
#implementation TableVC
- (void)viewDidLoad
{
[self fetchKinos];
[self.tableView reloadData];
[super viewDidLoad];
}
-(void)fetchKinos {
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:#"http://www.adworldmagazine.com/json.json"]];
NSError *error;
_kinos = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableView reloadData];
});
});
}
#pragma mark - Table view data source
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _kinos.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"KinoCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
//[self configureCell:cell atIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
NSArray *entities = [_kinos objectForKey:#"entities"];
NSDictionary *kino = [entities objectAtIndex:indexPath.row];
NSDictionary *title = [kino objectForKey:#"title"];
NSString *original = [title objectForKey:#"original"];
NSString *ru = [title objectForKey:#"ru"];
cell.textLabel.text = original;
cell.detailTextLabel.text = ru;
return cell;
}
#end
Your JSON response dictionary contains an array of entities whose count needs to be returned from the table view method.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [[self.kinos objectForKey:#"entities"] count];
}
Also, a suggestion, when you declare strong properties, try to access them as self.propertyName instead of accessing the ivar like _propertyName.
Hope that helps!
I accessed your url- http://www.adworldmagazine.com/json.json on my browser.
The response returns a JSON with root: dictionary.
So,
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return _kinos.count;
}
wont work.
Use this instead:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_kinos objectForKey:#"entities"].count;
}

how to read Plist data to UITableView [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to Get Data from a PList into UITableView?
I have a plist with Dictionary and numbers of strings per dictionary.show into the url below.and this list of items is in thousands in the plist.
Now want to display these list into the tableview
.
now how can i display this plist into the UITableView
what I am trying is:
- (id)readPlist:(NSString *)fileName
{
NSString *error;
NSPropertyListFormat format;
id plist;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:#"A" ofType:#"plist"];
dic =[NSDictionary dictionaryWithContentsOfFile:localizedPath];
plist = [NSPropertyListSerialization propertyListFromData:dic mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
if (!plist) {
NSLog(#"Error reading plist from file '%s', error = '%s'", [localizedPath UTF8String], [error UTF8String]);
[error release];
}
return plist;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
dict =[self readPlist:#"A"];
return dict.allKeys.count;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
dict = [self readPlist:#"A"];
key = [dict.allKeys objectAtIndex:section];
return [[dict valueForKey:key] 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 = [[dict objectForKey:key] objectAtIndex:indexPath.row];
return cell;
}
UPDATE 2: You need to set the delegate and datasource for your tableView in your xib or ViewController.
In your ViewController.h file
#interface ViewController:UIViewController <UITableViewDelegate, UITableDataSource>
Try this code which I have written for you.
- (void)viewDidLoad {
tableView.delegate = self;
tableView.dataSource = self;
NSString *path = [[NSBundle mainBundle] pathForResource:#"Filename" ofType:#"plist"];
NSArray *contentArray = [NSArray arrayWithContentsOfFile:path];
// Having outlet for tableArray variable.
tableArray = [[NSMutableArray alloc]initWithArray:contentArray copyItems:YES];
[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
return [tableArray count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// In your case dictionary contains strings with keys and values. The below line returns dictionary only. not array..
NSDictionary *dictionary = [tableArray objectAtIndex:section];
return dictionary.allKeys.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"MyCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cellIdentifier];
}
NSDictionary *dictionary = [tableArray objectAtIndex:indexPath.section];
NSArray *keysArray = dictionary.allKeys;
// This below line display the key in textLabel
cell.textLabel.text = [keysArray objectAtIndex:indexPath.row];
// Below line will display the value of a key in detailTextLabel.
cell.detailTextLabel.text = [dictionary valueForKey:[keysArray objectAtIndex:indexPath.row]];
return cell;
}
UPDATE 2: After I have seen your plist in my MAC, I have found out that we are working with array of dictionaries in your A.plist.
So I found there is a bug in our code itself. Not in the plist file and you can use your 8000 data plist too.. Its working too. I have checked out totally. Now you can get the above Code and start work with.
store Plist data in array
- (id)readPlist:(NSString *)fileName
{
NSString *error;
NSPropertyListFormat format;
id plist;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:#"A" ofType:#"plist"];
// declare your array in .h file
array = [NSArray arrayWithContentsOfFile:localizedPath];
plist = [NSPropertyListSerialization propertyListFromData:dic mutabilityOption:NSPropertyListImmutable format:&format errorDescription:&error];
if (!plist) {
NSLog(#"Error reading plist from file '%s', error = '%s'", [localizedPath UTF8String], [error UTF8String]);
[error release];
}
return plist;
}
and then write it in table
- (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 = [array objectAtIndex:indexPath.row] valueForKey:#"keyname"];;
return cell;
}

Display objects with specific string value in UITableView

If I want to display all the objects, I use the code below. But if I only want to display the objects where the value for the key "Favorite" = "Yes", then what? Example of this would be great.
- (void)viewDidLoad
{
[super viewDidLoad];
NSString *path = [[NSBundle mainBundle]
pathForResource:#"Objects" ofType:#"plist"];
sortedObjects = [[NSMutableArray alloc]initWithContentsOfFile:path];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [sortedObjects count];
}
Ps. The Property List is an array with dictionaries.
You need to create a new array, lets call it filtered, that you create by filtering sortedObjects, and use that to populate the table.
NSPredicate *pred = [NSPredicate predicateWithFormat:#"SELF.Favorite == %#", #"Yes"];
NSArray *filtered = [sortedObjects filteredArrayUsingPredicate:pred];
Try adding the following code.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *cellIdentifier = #"cellIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier] autorelease];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
{
if([[sortedObjects objectAtIndex:indexPath.row] valueForKey:#"Favorite"] isEqualToString:#"YES"])
{
//do stuff
}
}

UITableView crash on scroll

Whenever i scroll my UITableView, it looks at an array to find out what to fill the next cell with, but the array is empty, causing a crash, and appears to have been released somehow. Here is my code:
.h
#interface HomeViewController : UITableViewController {
NSArray *vaults;
}
#property (retain) NSArray *vaults;
#end
.m
#import "HomeViewController.h"
NSString *vaultsPath;
#implementation HomeViewController
#synthesize vaults;
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
vaultsPath = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents/Vaults"];
NSFileManager *fileManager = [NSFileManager defaultManager];
self.vaults = [fileManager contentsOfDirectoryAtPath:vaultsPath error:nil];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.vaults 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];
}
NSString *dictionaryPath = [NSString stringWithFormat:#"%#/%#",
vaultsPath,
[self.vaults objectAtIndex:indexPath.row]]; //Crashes at this line, with the self.vaults array now empty.
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:dictionaryPath];
cell = [AHCellCreation createCellWithDictionary:dictionary Cell:cell];
return cell;
}
- (void)dealloc
{
[super dealloc];
[self.vaults release];
}
#end
Any ideas?
My guess is the app crashes when you try to access the value of vaultsPath, which must be deallocated. Because the table view row count is based on the number of elements in the array, the method returning the cells, won't be called if there isn't any element in.
Try to retain the value assigned to vaultsPath, and don't forget to release it later.

I can't fill the cells of my UITableView with a NSArray (Normally it always works, but not in the case)

I have a UITableView with Cells that are filled with the Objects of an NSArray. I´m using the MGTwitterEngine to get Tweets from users. I want to show this tweets in the TableView. Here is the method that is called when the MGTwitterEngine has received all tweets ("namen" and "nachricht" are NSArrays):
- (void)statusesReceived:(NSArray *)statuses forRequest:(NSString *)connectionIdentifier
{ NSLog(#"Got statuses for %#:\r%#", connectionIdentifier, statuses);
NSDictionary *userDict = [statuses valueForKey:#"user"];
namen = [[NSArray alloc] initWithObjects: [userDict valueForKey:#"name"], nil];
nachricht = [statuses valueForKey:#"text"];
NSLog(#"%#", namen);
NSLog(#"%#", nachricht);
[table reloadData];
}
Then I did this to fill the cells with the names of the Twitter-users:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [nachricht count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
}
NSUInteger row = [indexPath row];
cell.textLabel.text = [arryData objectAtIndex:indexPath.row];
return cell;
}
Unfortunately, the app crashes whenever the table is reloaded: [table reloadData];. I know that the NSArray got all the right values, because NSLog shows me that. I've tried also to create a other NSArray, like that:
arryData = [[NSArray alloc] initWithObjects:#"iPhone",#"iPod",#"MacBook",#"MacBook Pro",nil];
And I written this into the cellforRowAtIndexPath-methode and and everything worked well. Why does it not work with the "namen"-NSArray?
The NSArray is probably being released - have you examined what's at its memory address?