I am new to parsing jSON file in objective C and I want to parse Twitter json feeds users names from the list.
I am trying to get the list of followers of a user and parse them to get the user_ids and then again call another URL to get their names and profile pics.
I am getting the names of the persons but I am not able to parse the list correctly.
If anybody can help me out here, it will be really helpful.
My code for fetching the data :
-(void) fetchData{
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
[account requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error){
if (granted == YES) {
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
if ([arrayOfAccounts count] > 0) {
ACAccount *acct = [arrayOfAccounts objectAtIndex:0];
NSString *username = acct.username;
NSLog(#"Account : %#", username);
TWRequest *fetchFriendsFollowers = [[TWRequest alloc]
initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/followers/ids.json?screen_name=%#",acct.username]]
parameters:nil
requestMethod:TWRequestMethodGET];
[fetchFriendsFollowers performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error){
if ([urlResponse statusCode] == 200 ) {
dispatch_async(dispatch_get_main_queue(), ^{
NSError *jsonParsingError = nil;
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
self.responseArray = [response objectForKey:#"ids"];
for (int i =0 ; i < [self.responseArray count]; i++) {
NSString *user_id = [self.responseArray objectAtIndex:i];
TWRequest *fetchFriendsFollowersNames = [[TWRequest alloc]
initWithURL:[NSURL URLWithString:[NSString stringWithFormat:#"https://api.twitter.com/1/users/lookup.json?user_id=%#",user_id]]
parameters:nil
requestMethod:TWRequestMethodPOST];
[fetchFriendsFollowersNames performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error){
if ([urlResponse statusCode] == 200 ) {
dispatch_async(dispatch_get_main_queue(), ^{
NSError *jsonParsingError = nil;
NSArray *response = [NSJSONSerialization JSONObjectWithData:responseData options:0 error:&jsonParsingError];
for (NSDictionary *user in response) {
[self.userNameArray addObject:[user objectForKey:#"name"]];
[self.tableView reloadData];
}
});
}
}];
}
NSLog(#"responseArray %# for user: %#",self.responseArray,username);
});
}
}];
}
else{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:#"Please add twitter accounts on your phone and log back in."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil];
[alert show];
}
}
}];
}
And then I am displaying it in cellForRowAtIndexPath the list of all the user names. It actually gets the list and repeats the name in all the cells. I know I am doing something silly mistake but cannot figure out since i have been looking at this for a while and cant get it fix.
- (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];
}
for (int i=0; i < [self.userNameArray count]; i++) {
NSLog(#"Text : %#", [self.userNameArray objectAtIndex:i]);
cell.textLabel.text = [self.userNameArray objectAtIndex:i];
}
return cell;
}
- (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 = [self.userNameArray objectAtIndex:indexPath.row];
NSLog(#"Text : %#", [self.userNameArray objectAtIndex:indexPath.row]);
return cell;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [self.userNameArray count];
}
indexPath.row does the work here No need for looping through the array, the tableview will call each object in the array for each cell.
Related
I want to pass values inside for(NSDictionary *jsonDictionary in myJsonArray) which I get in NSLog to [array addObject:[[SaveList alloc] initWithEmail:email withPhone:phone withDate:date withName:name]];
Code is here
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSURL *url = [NSURL URLWithString:#" http:// Some url "];
NSString *json = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
NSLog(#"\n\n JSON : %#, \n Error: %#", json, error);
if(!error)
{
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSArray *myJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
// NSDictionary *jsonDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:kNilOptions error:&error];
for(NSDictionary *jsonDictionary in myJsonArray)
{
NSLog(#"JSON Dictionary = %#", jsonDictionary);
NSString *name = jsonDictionary[#"Name"];
NSString *date = jsonDictionary[#"Date"];
NSString *email = jsonDictionary[#"Email"];
NSString *phone = jsonDictionary[#"Phone"];
NSLog(#"Name = %#", name);
NSLog(#"Date = %#", date);
NSLog(#"Email = %#", email);
NSLog(#"Phone = %#", phone);
}
}
});
//Table implementation
array = [[NSMutableArray alloc]init];
//**Get email, phone, date, name here**
[array addObject:[[SaveList alloc] initWithEmail:email withPhone:phone withDate:date withName:name]];
self.tableView.dataSource = self;
self.tableView.delegate = self;
Why don't you add the objects as you receive them? Since this block of code will be executed asynchronously you could prepare your array, set your tableview and then execute the block where you fill your array and refresh the tableview.
Something like this:
// Prepare your array
array = [NSMutableArray arrayWithCapacity:0];
// Set your tableview's datasource & delegate
self.tableView.dataSource = self;
self.tableView.delegate = self;
// Fetch data asynchronously
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
NSError *error = nil;
NSURL *url = [NSURL URLWithString:#" http:// Some url "];
NSString *json = [NSString stringWithContentsOfURL:url encoding:NSASCIIStringEncoding error:&error];
NSLog(#"\n\n JSON : %#, \n Error: %#", json, error);
if(!error)
{
NSData *jsonData = [json dataUsingEncoding:NSASCIIStringEncoding];
NSArray *myJsonArray = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:nil];
NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:myJsonArray.count];
for(NSDictionary *jsonDictionary in myJsonArray)
{
NSString *name = jsonDictionary[#"Name"];
NSString *date = jsonDictionary[#"Date"];
NSString *email = jsonDictionary[#"Email"];
NSString *phone = jsonDictionary[#"Phone"];
//**Get email, phone, date, name here**
[tmp addObject:[[SaveList alloc] initWithEmail:email
withPhone:phone
withDate:date
withName:name]];
}
// Reload your tableview
dispatch_sync(dispatch_get_main_queue(), ^{
array = tmp; // Or add them to your datasource array, whatever suits you...
[self.tableView reloadData];
});
}
});
set number of rows
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
[array count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
SavedList *savedList = [array objectAtIndex:indexPath.row];
cell.text = savedList.name;
}
return cell;
}
I hope it will be helpful.
// U need to reload table view data whenever you add new object in it. It does work like a thread.
dispatch_sync(dispatch_get_main_queue(), ^{
array = myJsonArray;
[self.tableView reloadData];
I am developing an iphone application. In this i have to generate user profile form dynamically according to field information coming from the server.
So, if there are 5 fields in response i want ton create 5 labels from those data to display in cell of uitableview.
Not that i am getting the name of fields for user profile, not the values of profile.
I want to generate form dynamically from those data.
I'm able to get those data in NSMutableArray but in cellForRowAtIndexPath method its showing null.
How can i solve this?
My code snippet is as follow.
-(void) connectionDidFinishLoading:(NSURLConnection *)connection {
if (connection)
{
NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
//You've got all the data now
//Do something with your response string
// NSLog(#"Response:%#",responseString);
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *object = [parser objectWithString:responseString error:nil];
NSString *pec_count = [object valueForKey:#"peculiarity_count"];
NSDictionary *pecs = [object valueForKey:#"peculiarities"];
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:nil];
[array addObject:#""];
for (int j= 1; j <= [pec_count integerValue] ; j++) {
NSString *val = [NSString stringWithFormat:#"%#%d",#"pec_",j];
NSString *pec_i = [pecs valueForKey:val];
NSString *modifiedString = [pec_i stringByReplacingOccurrencesOfString:#"_" withString:#" "];
NSString *capitalisedSentence = [modifiedString stringByReplacingCharactersInRange:NSMakeRange(0,1)
withString:[[modifiedString substringToIndex:1] capitalizedString]];
[array insertObject:capitalisedSentence atIndex:j];
}
self.peculiarity = array;
[self.table reloadData];
}
for (int j=0 ; j < [self.peculiarity count] ; j++) {
NSLog(#"info:%#", [self.peculiarity objectAtIndex: j]);
}
}
- (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];
UIButton *racebtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
racebtn.frame = CGRectMake(240, 7, 10, 15);
[racebtn setBackgroundImage:[UIImage imageNamed:#"select.png"] forState:UIControlStateNormal];
[racebtn addTarget:self action:#selector(selectRace:)forControlEvents:UIControlEventTouchUpInside];
NSLog(#"cell=%#",[self.peculiarity objectAtIndex:3]);
}
Any help will be appreciated.
Thank you.
in connectionDidFinishLoading: method replace the following line:
self.peculiarity = array; with,
self.peculiarity = [[NSMutableArray alloc] initWithArray:array];
and in cellForRowAtIndexPath method add the following line of code:
cell.textLabel.text = [self.peculiarity objectAtIndex:indexPath.row];
hope this will help you.
Note: If you did not allocated self.peculiarity NSMutableArray then alloc that array like bellow..
if (self.peculiarity == nil)
self.peculiarity = [[NSMutableArray alloc] init];
and then assign that array to this array like bellow..
self.peculiarity = array;
after in cellForRowAtIndexPath: method just set that value or name to the textLabel Of the UITableViewCell like bellow..
cell.textLabel.text = [self.peculiarity objectAtIndex:indexPath.row];
see whole example with that method..
- (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];
UIButton *racebtn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
racebtn.frame = CGRectMake(240, 7, 10, 15);
[racebtn setBackgroundImage:[UIImage imageNamed:#"select.png"] forState:UIControlStateNormal];
[racebtn addTarget:self action:#selector(selectRace:)forControlEvents:UIControlEventTouchUpInside];
[cell addSubview:racebtn];
cell.textLabel.text = [self.peculiarity objectAtIndex:indexPath.row];
}
return cell;
}
I already have checked all above solutions before, Then finally i got solution for this. The problem was that my cell was getting loaded before arrival of data. So i used synchronous request to the server.
Code is below for this :
NSString *path = [[NSBundle mainBundle] objectForInfoDictionaryKey:#"path"];
NSString *address = [NSString stringWithFormat:#"%#%#%#%#", path,#"users/",#"peculiarity/",self.tablename];
NSURL *URL = [NSURL URLWithString:address];
NSLog(#"%#",address);
[NSURLRequest setAllowsAnyHTTPSCertificate:YES forHost:[URL host]];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL cachePolicy:NSURLCacheStorageAllowedInMemoryOnly
timeoutInterval:60.0];
[request setHTTPMethod:#"GET"];
NSURLResponse *response = nil;
NSError *error = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
if (data) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
NSLog(#"data:%#",responseString);
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSDictionary *object = [parser objectWithString:responseString error:nil];
pecs = [object valueForKey:#"pec_values"];
for (int j =0; j < [pecs count] ; j++) {
NSLog(#"values:%#",[pecs objectAtIndex:j]);
}
self.peculiarity = array;
}
else {
// Handle error by looking at response and/or error values
NSLog(#"%#",error);
}
I'm new to iPhone development,I'm trying to bind data from JSON Url in UITableview, but I'm getting an error in the below code.
- (void)viewDidLoad
{
SBJsonParser *parser = [[SBJsonParser alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://80f237c226fa45aaa09a5f5c82339d46.cloudapp.net/DownloadService.svc/Courses"]];
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:nil];
NSString *json_string = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
statuses = [parser objectWithString:json_string error:nil];
[self.dropdownTblView reloadData];
for (NSDictionary *status in statuses)
{
_altTitle = [status valueForKey:#"Title"];
NSLog(#"Title %#",_altTitle);
}
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%d",[statuses count]);
return [statuses 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];
}
return cell;
//Here I'm getting an error
id obj = [statuses objectAtIndex:indexPath.row];
NSString *name = [obj valueForKey:#"Title"];
cell.textLabel.text =name;
return cell;
}
This is my JSON
[
{
"Id": 1,
"Title": "Tamil to English",
"AltTitle": "த|மி|ழ்| |மூ|ல|ம்| |ஆ|ங்|கி|ல|ம்",
"Description": "Learn English through Tamil",
"Code": 1,
"Version": "1.0",
"SourceLanguageIndicator": "அ",
"TargetLanguageIndicator": "A",
"SourceLanguageCode": "ta",
"TargetLanguageCode": "en",
"Updated": "2013-02-21T03:33:19.6601651+00:00"
}
]
Any ideas? Thanks in advance.
You're returning the cell twice in the same scope, try to delete the first return cell;, also you're calling reloadData on the table just before the for loop; in this case probably the dataSource of the table is still empty, so call reloadData just after the for loop.
EDIT:
It's strange what is happening, the objectFromString must return a NSArray or a NSDictionary but it seems that is pointing to an NSSet. I can suggest 2 things in addition:
It seems that you're not usig ARC since you're calling autorelease on the UITableViewCell. In this case you're leaking parser and json_string in the viewDidLoad, so release them.
Make sure to call [super viewDidLoad]; (you're not doing this in your code).
Maybe because you set the type of obj as id. It is too generic and may not know how to respond to valueForKey. Have you tried declaring obj as an NSDictionary * instead? Like the code below:
NSDictionary *obj = [statuses objectAtIndex:indexPath.row];
NSString *name = [obj valueForKey:#"Title"];
Use the Below code in your ViewDidload and Run the Project , it will work.
Note :You're returning the cell twice, try to delete the first return
cell;
- (void)viewDidLoad
{
[super viewDidLoad];
statuses=[[NSMutableArray alloc]init];
NSURL *myURL = [NSURL URLWithString:#"http://80f237c226fa45aaa09a5f5c82339d46.cloudapp.net/DownloadService.svc/Courses"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:myURL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSLog(#"Finished with status code: %i", [(NSHTTPURLResponse *)response statusCode]);
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:nil];
NSLog(#"jsonObject=%#",jsonObject);
statuses=[jsonObject mutableCopy];
[self.coursetable reloadData];
}];
NSLog(#"myURL=%#",myURL);
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
NSLog(#"%d",[statuses count]);
return [statuses 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] ;
}
id obj = [statuses objectAtIndex:indexPath.row];
cell.textLabel.text =[obj valueForKey:#"Title"];
return cell;
}
Yes I was thinking right, statuses is not NSArray, it is NSSet so if you call objectAtIndex on NSSet it will crash.To get array convert NSSet into NSArray.
NSArray *array =[statuses allObjects];
- (void)viewDidLoad
{
NSString *dictStr=#"{\"Id\": 1,\"Title\": \"Tamil to English\",\"AltTitle\": \"த|மி|ழ்| |மூ|ல|ம்| |ஆ|ங்|கி|ல|ம்\",\"Description\": \"Learn English through Tamil\",\"Code\": 1,\"Version\": \"1.0\",\"SourceLanguageIndicator\": \"அ\",\"TargetLanguageIndicator\": \"A\",\"SourceLanguageCode\": \"ta\",\"TargetLanguageCode\": \"en\",\"Updated\": \"2013-02-21T03:33:19.6601651+00:00\"}";
NSDictionary *rootDict =[NSJSONSerialization JSONObjectWithData: [dictStr dataUsingEncoding:NSUTF8StringEncoding]
options: NSJSONReadingMutableContainers
error: nil];
NSArray *keys=[[rootDict allKeys] sortedArrayUsingSelector:#selector(compare:)];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [keys count];
}
- (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];
}
cell.textLabel.text=[rootDict valueForKey:[keys objectAtIndex:indexPath.row]];
return cell;
}
remember rootDict and keys will be declared as global.
Im trying to get deep into a nested JSon Array, i have successfully done it for the level above but I cant work out how to get any deeper.
I need to log the image #url I have attached a screen show to show where i need it to go.
Thanks :)
- (void)viewDidLoad
{
[super viewDidLoad];
[UIApplication sharedApplication].networkActivityIndicatorVisible = YES;
NSURL *url = [NSURL URLWithString:#"http://api.storageroomapp.com/accounts/511a4f810f66026b640007b8/collections/511a51580f66023bff000ce9/entries.json?auth_token=Zty6nKsFyqpy7Yp5DP1L&preview_api=1"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
-(void)connectionDidFinishLoading:(NSURLConnection *) connection{
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSDictionary *dictionary = [NSJSONSerialization JSONObjectWithData:data options:nil error:nil];
NSDictionary *arrayDictionary = dictionary[#"array"];
news = arrayDictionary[#"resources"];
[tableView reloadData];
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
UIAlertView *errorView = [[UIAlertView alloc] initWithTitle:#"Error" message:#"The data could not be downloaded - please make sure you're connected to either 3G or Wi-FI" delegate:nil cancelButtonTitle:#"Dismiss" otherButtonTitles:nil];
[errorView show];
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
}
-(int)numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}
-(int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return [news count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSDictionary *newsItem = news[[indexPath row]];
NSString *title = newsItem[#"title"];
NSString *date = newsItem[#"date"];
NSString *thumb = newsItem[#"tablethumb"];
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"MainCell"];
if (cell == nil) {
cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"MainCell"];
[[cell textLabel] setText:title];
[[cell detailTextLabel] setText:date];
if((NSNull *)thumb == [NSNull null]){
NSLog(#"no image");
} else{
NSLog(# "image = %#", thumb);
}
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
For traversing nested objects you could use valueForKeyPath method and use the dot syntax to drill down the hieararchy.
Something like this would fetch the url value from your newsItem dictionary:
NSDictionary *newsItem = news[[indexPath row]];
NSString *thumbUrl = [newsItem valueForKeyPath:#"tablethumb.url"];
PS. If you really have the properties prefixed by # then you might get into trouble by using valueForKeyPath since # is a special token used as an operator. In this case you could do something like this instead:
NSDictionary *newsItem = news[[indexPath row]];
id tablethumb = [newsItem objectForKey:#"tablethumb"];
NSString *thumbUrl = #"";
// Check if not null and access the #url
if (tablethumb != [NSNull null])
thumbUrl = tablethumb[#"#url"];
Try to access value from dictionary like this,
NSLog(#"URL: %#",[newsItem objectForKey:#"#url"]);
I have a JSON file, and i need to extract values from it and display on my tableview. Everything works fine.
{
"1": {
"name": "Jemmy",
"birthday": "1994-11-23"
},
"2": {
"name": "Sarah",
"birthday": "1994-04-12"
},
"3": {
"name": "Deb",
"birthday": "1994-11-23"
},
"4": {
"name": "Sam",
"birthday": "1994-11-23"
}
}
When i display the values, it doesn't get displayed in the order of 1,2,3,4 as given in the records. It just gets displayed randomly. I have included my code below, I need it to be modified so i could display the content in the order given above. Can someone please help ?
- (void)requestSuccessfullyCompleted:(ASIHTTPRequest *)request{
NSString *responseString = [request responseString];
SBJsonParser *parser = [SBJsonParser new];
id content = [responseString JSONValue];
if(!content){
return;
}
NSDictionary *personDictionary = content;
NSMutableArray *personMutableArray = [[NSMutableArray alloc] init];
for (NSDictionary *childDictionary in personDictionary.allValues)
{
Deal *deal = [[Deal alloc] init];
deal.name=[childDictionary objectForKey:#"name"];
deal.dob=[childDictionary objectForKey:#"birthday"];
[personMutableArray addObject:deal];
}
self.personArray = [NSArray arrayWithArray:personMutableArray];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
Person *person = [self.personArray objectAtIndex:indexPath.row];
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
cell.namelabel.text=person.name;
cell.doblabel.text=person.dob;
}
return cell;
}
You're not reusing your cell correctly. If the cell is being reused, you fail to configure it.
Your cellForRowAtIndexPath: should be this way:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"Cell";
Cell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[Cell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:CellIdentifier];
}
Person *person = [self.personArray objectAtIndex:indexPath.row];
cell.namelabel.text=person.name;
cell.doblabel.text=person.dob;
return cell;
}
Note that this is correct ARC code, but in pre-ARC, you need to add autorelease to the end of the [Cell alloc] line.
Try this and also correct your cellForRowAtIndexPath: for reused cells
- (void)requestSuccessfullyCompleted:(ASIHTTPRequest *)request{
NSString *responseString = [request responseString];
SBJsonParser *parser = [SBJsonParser new];
id content = [responseString JSONValue];
if(!content){
return;
}
NSDictionary *personDictionary = content;
NSMutableArray *personMutableArray = [[NSMutableArray alloc] init];
NSArray *array = [personDictionary allKeys];
NSArray * sortedArray = [array sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
for (NSString *str in sortedArray)
{
NSDictionary *childDictionary = [personDictionary objectForKey:str];
Deal *deal = [[Deal alloc] init];
deal.name=[childDictionary objectForKey:#"name"];
deal.dob=[childDictionary objectForKey:#"birthday"];
[personMutableArray addObject:deal];
}
self.personArray = [NSArray arrayWithArray:personMutableArray];
}
You store the data from the JSON in a dictionary which doesn't store ordered data. You would have to get that data in order in an array or sort the array afterwords.
You could sort the array in which you store the dictionary data, if you wish to sort it alphabetically by name you can do this:
self.personArray = [personMutableArray sortedArrayUsingSelector:#selector(compare:)];
- (NSComparisonResult)compare:(Deal *)dealObject {
return [self.name compare:dealObject.name];
}
If you want the data to be represented just as the JSON you should do something like this:
for (int i = 1; i < [personDictionary.allValues count]; i++)
{
NSDictionary *childDictionary = [[personDictionary objectForKey:[NSString stringWithFormat:#"%d", i]];
Deal *deal = [[Deal alloc] init];
deal.name=[childDictionary objectForKey:#"name"];
deal.dob=[childDictionary objectForKey:#"birthday"];
[personMutableArray addObject:deal];
}