I have implemented a UITableview in VC1, and I want to display some JSON data in the cell. I have implemented a Model class to pass the data to the table view.
dispatch_async(dispatch_get_main_queue(), ^{
NSURLSession*session=[NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:#"https://itunes.apple.com/search?term=music"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"%#", json);
NSArray *entryarr = [json objectForKey:#"results"];
TableClass *tc = [[TableClass alloc] init];
for (NSDictionary *appDict in entryarr) {
//setting title
NSString *str = [appDict objectForKey:#"artistName"];
[tc setTittle:str];
NSLog(#"artist Name=%#",tc.tittle);
//setting Subtitle
NSString *sub = [appDict objectForKey:#"country"];
[tc setSubtittle:sub];
NSLog(#"artist Name=%#",tc.subtittle);
//image
NSString *imageStr = [appDict objectForKey:#"artworkUrl60"];
NSURL *imageURL = [NSURL URLWithString:imageStr];
[tc setImage:imageStr];
NSData *imageData =[[NSData alloc] initWithContentsOfURL:imageURL];
//[self.imageArray addObject:imageData];
[_tableArray addObject:tc];
NSLog(#"%# name of tittle",[_tableArray objectAtIndex:0]);
}
NSLog(#"%lu %lu %lu",(unsigned long)self.tableArray.count,(unsigned long)self.tableArray.count,(unsigned long)self.tableArray.count);
[self.tableView reloadData];
}];
[dataTask resume];
});
But, while accessing it to the cell I am getting the last element in the array.
TableClass *tableclassModel = [self.tableArray objectAtIndex:indexPath.row];
cell.textLabel.text = tableclassModel.tittle;
cell.detailTextLabel.text = tableclassModel.subtittle;
cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:tableclassModel.image]]];
Why is it so...? How can I do it?
You are changing the value of same tc object again and again. Since you have declared tc object outside for loop, there will be only one tc. You are adding it to _tableArray after making the required changes in the first iteration of the loop. In the second iteration, you are changing the value of same tc object used in first iteration and adding it to _tableArray again. This will update the first object also with the new values. This goes on and finally your _tableArray will contain n number of tc objects with the same values (i.e last updated value)
Give the declaration inside the for loop
dispatch_async(dispatch_get_main_queue(), ^{
NSURLSession*session=[NSURLSession sharedSession];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:#"https://itunes.apple.com/search?term=music"] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"%#", json);
NSArray*entryarr=[json objectForKey:#"results"];
for (NSDictionary*appDict in entryarr) {
TableClass*tc=[[TableClass alloc]init];
//setting tittl
NSString*str=[appDict objectForKey:#"artistName"];
[tc setTittle:str];
NSLog(#"artist Name=%#",tc.tittle);
//setting Subtittle
NSString*sub=[appDict objectForKey:#"country"];
[tc setSubtittle:sub];
NSLog(#"artist Name=%#",tc.subtittle);
//image
NSString*imageStr=[appDict objectForKey:#"artworkUrl60"];
NSURL*imageURL=[NSURL URLWithString:imageStr];
[tc setImage:imageStr];
NSData*imageData=[[NSData alloc]initWithContentsOfURL:imageURL];
//[self.imageArray addObject:imageData];
[_tableArray addObject:tc];
NSLog(#"%# name of tittle",[_tableArray objectAtIndex:0]);
}
NSLog(#"%lu %lu %lu",(unsigned long)self.tableArray.count,(unsigned long)self.tableArray.count,(unsigned long)self.tableArray.count);
[self.tableView reloadData];
}];
[dataTask resume];
});
Related
I make a call to the youtube API to get the title of a video. I then want to display the title of the video on the screen in a table. How do I access the title after the block has finished executing?
Here's the code to get the title
-(void)getVideoTitle:(NSString *)urlStr success:(void (^)(NSDictionary *responseDict))success{
urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/videos?part=contentDetails%%2C+snippet%%2C+statistics&id=%#&key={API_KEY}",urlStr];
NSURL *url = [[NSURL alloc] initWithString:urlStr];
// Create your request
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// Send the request asynchronously
[[[NSURLSession sharedSession] dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *connectionError) {
// Callback, parse the data and check for errors
if (data && !connectionError) {
NSError *jsonError;
NSDictionary *jsonResult = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
if (!jsonError) {
success(jsonResult);
// NSLog(#"Response from YouTube: %#", jsonResult);
}
}
}] resume];
}
Here's how I call the above function:
[self getVideoTitle:#"zB4I68XVPzQ" success:^(NSDictionary *responseDict){
NSArray *itemsArray = [responseDict valueForKey:#"items"];
NSDictionary *item = itemsArray[0];
NSDictionary* snippet = [item valueForKey:#"snippet"];
NSString *title = [snippet valueForKey:#"title"];
}];
How do I get access the title variable outside the block after the block has finished executing?
I have tried the following with no luck
dispatch_async(dispatch_get_main_queue(), ^{
[self updateMyUserInterfaceOrSomething];
});
In your code:
NSString* recievedTitle __block = nil; //title is here, after block below run
[self getVideoTitle:#"zB4I68XVPzQ" success:^(NSDictionary *responseDict){
NSArray *itemsArray = [responseDict valueForKey:#"items"];
NSDictionary *item = itemsArray[0];
NSDictionary* snippet = [item valueForKey:#"snippet"];
recievedTitle = [snippet valueForKey:#"title"]; //here you write it
// or
NSString *title = [snippet valueForKey:#"title"];
[self updateInterfaceWithTitle: title]
}];
///
- (void)updateInterfaceWithTitle:(NSString*)title{
//use title here
}
I ma doing program in WebService...
In main viewController....
AppListTableViewController *appList = [self.storyboard instantiateViewControllerWithIdentifier:#"ALTVC"];
self.dataTask = [self.urlSession dataTaskWithRequest:self.urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSMutableDictionary *serverRes = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *imageLink = [[[[[[serverRes objectForKey:#"feed"] objectForKey:#"entry"] objectAtIndex:0] objectForKey:#"im:image"] objectAtIndex:0] objectForKey:#"label"];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:imageLink forKey:#"image"];
[self.dataTask resume];
}
[self.navigationController pushViewController:appList animated:YES];
From server image link came successfully... but how to send and display that image in tableView cell.
In tableView controller ....
cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[defaults objectForKey:#"image"]]]];
It's not display any image in cell...
the reason you were pushed your VC before completion on call, do like
self.dataTask = [self.urlSession dataTaskWithRequest:self.urlRequest completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSMutableDictionary *serverRes = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *imageLink = [[[[[[serverRes objectForKey:#"feed"] objectForKey:#"entry"] objectAtIndex:0] objectForKey:#"im:image"] objectAtIndex:0] objectForKey:#"label"];
if (imageLink)
{
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:imageLink forKey:#"image"];
// call your navigation inside the block
AppListTableViewController *appList = [self.storyboard instantiateViewControllerWithIdentifier:#"ALTVC"];
[self.navigationController pushViewController:appList animated:YES];
}
}];
[self.dataTask resume];
I have an iOS app with a table view and I want to get the table items from an extern php file which gives me a json string. Now I try to store the data from the php file to the data variable. Here is my code:
- (NSMutableArray *)data {
if(!_data){
_data = [[NSMutableArray alloc] init];
NSURLSession *session = [NSURLSession sharedSession];
NSString *url = [NSString stringWithFormat:#"http://www.example.net/something/bla.php"];
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:[NSURL URLWithString:url] completionHandler:^(NSData *data, NSURLResponse *response, NSError *error){
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSString *errorCode = [json valueForKey:#"error"];
if([errorCode isEqualToString:#"e0"]){
NSArray *persons = [json objectForKey:#"persons"];
for (int i = 0; i < [persons count]; i++) {
NSString *person = [[persons objectAtIndex:i] objectForKey:#"name"];
[_data addObject:person];
}
}
NSLog(#"3.: %#", _data); // Full
}];
[dataTask resume];
NSLog(#"2.: %#", _data); // Empty
}
NSLog(#"1.: %#", _data); // Empty
return _data;
}
How can I return the result of the url session now? As you can see on my comments, the _data array is only filled on NSLog 3 and it is empty on 1 and 2. Would be nice if someone could tell me what I must change.
I am trying to get a value from an NSDictionary and put it into an NSMutableArray. Here's some of my code for example.
- (IBAction)pressedButton:(id)sender {
NSInteger numberOfResults = 3;
NSString *searchString = #"EMINEM";
NSString *encodedSearchString = [searchString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSString *finalSearchString = [NSString stringWithFormat:#"https://itunes.apple.com/search?term=%#&entity=song&limit=%li",encodedSearchString,(long)numberOfResults];
NSURL *searchURL = [NSURL URLWithString:finalSearchString];
dispatch_queue_t iTunesQueryQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(iTunesQueryQueue, ^{
NSError *error = nil;
NSData *data = [[NSData alloc] initWithContentsOfURL:searchURL options:NSDataReadingUncached error:&error];
if (data && !error) {
NSDictionary *JSON = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSArray *array = [JSON objectForKey:#"results"];
NSMutableArray *arrayTracks;
for (NSDictionary *bpDictionary in array) {
[arrayTracks addObject:[bpDictionary objectForKey:#"trackName"]];
// _author = [bpDictionary objectForKey:#"trackName"];
dispatch_async(dispatch_get_main_queue(), ^{
self.label.text = [arrayTracks objectAtIndex:0];
// self.label2.text = _author;
// NSLog(#"%#", [array objectAtIndex:0]);
});
}
}
});
}
As you can see from the above, it does not properly put the value into the array. If I set the _author to [bpDictionary objectForKey:#"trackName"] then it does work, but it goes through it all and sets the label as the last in the array. The above code outputs nothing (null).
Leverage foundation to your advantage, there's no need to iterate the array manually.
To get an array of track names you can simply use valueForKey: or valueForKeyPath:
NSArray *trackNames = [JSON valueForKeyPath:#"results.trackName"];
That being said, I urge you to perform networking tasks with networking API. You should never be using NSData to retrieve JSON. Stick to NSURLSession, it's cleaner and designed for networking tasks.
[[[NSURLSession sharedSession] dataTaskWithURL:itunesSearchURL
completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
// now you have a properly downloaded JSON
//and you even have access to the URL response headers and any errors.
}]resume];
Edit
As an aside, you never initialize your array of trackNames so calling addObject on a nil value will have no effect.
how can i display image into UICollectionView using Cache and display large image into another
View on UICollectionView didSelect. Here both large and thumb image on CollectionView so next view large image not blank.using EMAsyncImageView
NSURL *url = [NSURL URLWithString:#"http://leewayinfotech.com/mobile/girlwallpaper/api.php?category=abstract&device=i5&hits=all"];
NSURLRequest *req = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:req queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
//NSLog(#"Response String=%#",responseString);
NSError *jsonError;
NSData *trimmedData = [responseString dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:trimmedData options:NSJSONReadingAllowFragments error:&jsonError];
if (jsonError) {
NSLog(#"JSON parse error: %#", jsonError);
return;
}
obj_Array=[[NSMutableArray alloc] init];
obj_Array=[json objectForKey:#"wallpaper"];
//NSMutableArray *tmp = [NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.thumb_img_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.device_img_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
imgPage.imgNo_Array=[NSMutableArray arrayWithCapacity:[obj_Array count]];
for (int i=0; i<[obj_Array count]; i++) {
ImgClass *obj_Class=[[ImgClass alloc] init];
obj_Class.main_id=[[[obj_Array objectAtIndex:i] valueForKey:#"id"] integerValue];
[obj_Class.thumb_img_Array addObject:[[[obj_Array objectAtIndex:i] objectForKey:#"images"] objectForKey:#"image_thumb"]];
[obj_Class.device_img_Array addObject:[[[obj_Array objectAtIndex:i] objectForKey:#"images"] objectForKey:#"image2"]];
NSLog(#"Thumb-->%#\n\nDevice-->%#",[obj_Class.thumb_img_Array description],[obj_Class.device_img_Array description]);
[appDelg.my_Array addObject:obj_Class];
}
you use the EGOImageView for image caching support.
You can use SDWebImage.Using SDWebImage you can set image using imageURLString like below with CacheType.
[yourImgView setImageWithURL:[NSURL URLWithString:imageURLString]
placeholderImage:[UIImage imageNamed:#"noimage.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType)
{
if (!error && image)
{
}
}];
Hope it will helps you..