Display JSON data in UITableView - iphone

My app is loading some data thought JSON and everything is working fine, but when I try to display those data in my UITableView cell, nothing happens. My code is below:
Get Data(JSON):
-(void)fetchedData:(NSData *)responseData {
NSError* error;
NSDictionary* json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
NSArray* latestLoans = [json objectForKey:#"loans"];
testeDictionary = [latestLoans objectAtIndex:0];
testeLabel.text = [NSString stringWithFormat:#"%#",[testeDictionary objectForKey:#"id"]];
testeString = [testeDictionary objectForKey:#"username"];
[miArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:testeString,#"username",nil]];
}
UITableView :
-(UITableViewCell *)tableView:(UITableView *)myTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = (UITableViewCell *)[self.settingsTableView dequeueReusableCellWithIdentifier:#"CellD"];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CellD" owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
}
if ([indexPath row] == 0) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"CellA" owner:self options:nil];
cell = (UITableViewCell *)[nib objectAtIndex:0];
NSDictionary *itemAtIndex = (NSDictionary *)[miArray objectAtIndex:indexPath.row];
UILabel *usernameString = (UILabel *)[cell viewWithTag:1];
usernameString.text = [itemAtIndex objectForKey:#"id"]; <== MUST DISPLAY JSON VALUE
}
return cell;
}
More clearly I need to display this [testeDictionary objectForKey:#"id"] on the usernameString.text?

You are not storing the id
[miArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:testeString,#"username",nil]];
I suppose what you want to be doing is something like this
NSString *idString = [NSString stringWithFormat:#"%#", [testeDictionary objectForKey:#"id"]];
[miArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:
testeString, #"username",
idString, #"id",
nil]];
EDIT (explanation)
In your method fetchedData: you extract the id and set the text of some label to the id.
testeLabel.text = [NSString stringWithFormat:#"%#",[testeDictionary objectForKey:#"id"]];
After that you forget about the id. You then proceed to extract the username and you create a dictionary containing only the username and add that dictionary to an array called miArray.
[miArray addObject:[NSDictionary dictionaryWithObjectsAndKeys:testeString,#"username",nil]];
Notice that you do not specify any key named "id".
Later, you fetch a dictionary from miArray. This dictionary is the one you created with only one key, i.e. "username". You tell it to get an object for the key "id", but since you never specified that key, you get a nil value.
Bottom line, try my solution.

Related

JSON Object to NSArray

I have to following JSON response from a server:
{
"theSet": [
],
"Identifikation": 1,
"Name": "Casper",
"Adress": "Lovis 23",
"Location": "At home",
"Information": "The first, the second and the third",
"Thumbnail": "none",
}
I am retrieving the data like so:
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
NSLog(#"connectionDidFinishLoading");
NSLog(#"Succeeded! Received %d bytes of data",[data length]);
NSError *myError = nil;
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];
news = [NSArray arrayWithObjects:[res allKeys], [res allValues], nil];
NSLog(#"%#", news);
//[mainTableView reloadData];
}
Then I want to insert all the JSON data into an array, so I can display the data in my tableview.
My tableview code:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"Name"];
cell.detailTextLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"Adress"];
return cell;
}
But my app crashes with the error:
-[__NSArrayI objectForKey:]: unrecognized selector sent to instance.
How can I insert the JSON object into an NSArray, so I can display it in my tableview?
EDITED:
I reviewed your code again and what I previously answered was wrong.
When generating your news, you are putting 2 NSArray objects in it. The first containing all keys, and the second containing all values in your JSON.
In order to display the names of each object in your JSON, you should be simply doing
news = [res allKeys];
jsonResult = res;
// store your json if you want to use the values!
Note they will be unordered.
On your cell, you can do:
NSString *key = [news objectAtIndex:indexPath.row];
cell.textLabel.text = key;
id object = [jsonResult valueForKey:key];
cell.detailTextLabel.text = // do something depending on your json type which can have different values
The error you have
[__NSArrayI objectForKey:]: unrecognized selector sent to instance.
Tells you everything you need to know.
This says NSArray does not understand objectForKey. If you read the documentation provided by Apple, you will see this.
Your code
cell.textLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"Name"];
Is expecting the news NSArray to return an object that responds to objectForKey - most likely an NSDictionary. The code you have for extracting your JSon data
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&myError];
news = [NSArray arrayWithObjects:[res allKeys], [res allValues], nil];
Is just taking all of the dictionaries and extracting the keys into the array.
You need to look at these lines of your code - this is where you are going wrong.
Look at the NSJSONSerialization reference and the releated sample code that it links to.
I found a simple solution myself, that fits my project better:
I just did the following:
NSDictionary *res = [NSJSONSerialization JSONObjectWithData:data options:0 error:&myError];
NSArray news = [NSArray arrayWithObject:res];
and with that I am able to use the following code to display the JSON contents in my tableview.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
}
cell.textLabel.text = [[news objectAtIndex:indexPath.row] valueForKey:#"name"];
cell.detailTextLabel.text = [[news objectAtIndex:indexPath.row] objectForKey:#"Location"];
return cell;
}

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

Reading url image from plist string

I have a plist with dictionary.
In the dictionary i have a string called "cellPic" that have url address of an image.
I'm trying to populate my table view with images that i put on my dropbox account & read them through the plist string.
("arrayFromPlist" is my array)
The problem is that when i run it, i'm getting an error in the console:
[__NSCFDictionary objectAtIndex:]: unrecognized selector
This is my code:
-(void) readPlistFromDocs
{
// Path to the plist (in the Docs)
NSString *rootPath =
[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistPath = [rootPath stringByAppendingPathComponent:#"Data.plist"];
NSLog(#"plistPath = %#",plistPath);
// Build the array from the plist
NSMutableArray *arrayFromDocs = [[NSMutableArray alloc] initWithContentsOfFile:plistPath];
if (arrayFromDocs)
{
NSLog(#"\n content of plist file from the documents \n");
NSLog(#"Array from Docs count = : %d", [arrayFromDocs count]);
}
arrayFromPlist = [[NSArray alloc] initWithArray:arrayFromDocs];
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
// Returns the number of rows in a given section.
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [arrayFromPlist count];
NSLog(#"Array SIZE = %d",[arrayFromPlist count]);
}
- (UITableViewCell *)tableView:(UITableView *)aTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [aTableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
NSURL *url = [[NSURL alloc] initWithString:[[arrayFromPlist objectAtIndex:indexPath.row] objectForKey:#"cellPic"]];
NSData *urlData = [[NSData alloc] initWithContentsOfURL:url];
[[cell imageView] setImage:[UIImage imageWithData:urlData]];
return cell;
}
My other question is - how can i load the images asynchronous when i read the url from the plist string?
I tried to find an example for that but i found only asynchronous without uisng plist.
Thanks.
Change Following line
NSDictionary *arrayFromDocs = [[NSDictionary alloc] initWithContentsOfFile:plistPath];
Best Tutorial for load the images asynchronous
Hope, this will help you..

Saving data to a plist file

I am having a little trouble saving to a plist file, when i am reading the data i am using:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return amounts.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
//Create Cell
UITableViewCell *cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:#"cell"];
//Fill cell
NSDictionary *budgetItem = [amounts objectAtIndex:indexPath.row];
cell.textLabel.text = [budgetItem objectForKey:#"value"];
cell.detailTextLabel.text = [budgetItem objectForKey:#"description"];
//Return it
return cell;
}
- (void) loadData{
// Load items
NSString *error;
NSPropertyListFormat format;
NSString *localizedPath = [[NSBundle mainBundle] pathForResource:#"savebudget" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:localizedPath];
NSArray *amountData = [NSPropertyListSerialization propertyListFromData:plistData
mutabilityOption:NSPropertyListImmutable
format:&format
errorDescription:&error];
if (amountData) {
self.amounts = [[NSMutableArray alloc] initWithCapacity:[amountData count]];
for (NSDictionary *amountsDictionary in amountData) {
[self.amounts addObject:amountsDictionary];
}
}
Which works fine from a static plist file with-in my resources folder, but when i try and create my own, nothing seems to happen:
-(void) addData {
NSString *path = [[NSBundle mainBundle] pathForResource:#"saveBudget" ofType:#"plist"];
NSMutableDictionary* plist = [[NSMutableDictionary alloc] initWithContentsOfFile:path];
[plist setValue:amountTxt.text forKey:#"value"];
[plist writeToFile:path atomically:YES];
[plist release];
}
- (IBAction)add:(id)sender {
[self addData];
[self.delegate budgetEnterMinusViewControllerDidFinish:self];
}
Any help more than welcome...
Ugh. Terrible and confusing code. First: use this to load instead:
NSString* path = [[NSBundle mainBundle] pathForResource:#"savebudget" ofType:#"plist"];
NSDictionary* amountData = [NSDictionary dictionaryWithContentsOfFile: path error: NULL];
if (amountData) {
self.amounts = [NSMutableArray arrayWithArray: amountData];
}
Note, no retain or alloc/init here because you are assigning to a retaining property.
So the real problem:
You are reading a plist that that you say contains an array of dictionaries. But then when you add data, you try to write back one single dictionary to that same plist.
Also, in your addData method you do not actually add any data.
And ... If you load your initial data from your app's bundle, then you should write it back to your ~/Documents directory after changing it. And of course read it back from there the next time your app starts.

How to solve slow scrolling in UITableView

I'm testing for the first time on a real device, and after fixing some obvious performance problems, I'm stuck on how do smooth scrolling.
This is what I do:
The data is in sqlite
I have a small array with the header
I have in each header array the list of Id's from the Db
e.g.
Header A
Ids= 1,2;
Header B
Ids= 3,4
I lazy load the cell & the object to get the data
Barely 10 items are loaded at a time
Loading is fast, only scrolling is a issue
This is the code on the loading of the cell:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"ProductCell";
ProductCell *cell = (ProductCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"ProductCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
}
// Set up the cell...
Product *p = [self locateRecord:indexPath];
cell.nameLabel.text = [p.name capitalizedString];
cell.codeLabel.text = p.ref;
if ([self.selectedProducts objectForKey:[NSNumber numberWithInt:p.Id]]) {
OrderDetail *d = [self findDetail:p];
cell.qty.text = [NSString stringWithFormat:#"%ld",[d.qty integerValue]];
}
return cell;
}
- (id) locateRecord:(NSIndexPath *)indexPath {
NSNumber *theId;
NSUInteger pos = [indexPath row];
id o;
if (self.results) {
theId = [self.results objectAtIndex:pos];
} else {
NSString *key = [[self.index objectAtIndex:[indexPath section]] objectAtIndex:0];
NSArray *data = [self.cache objectForKey:key];
theId = [data objectAtIndex:pos];
}
Db *db= [Db currentDb];
o = [db loadById:[self returnItemClass] theId:[theId intValue]];
return o;
}
Preload the data
Do your own drawing