I have to show some post blogs into a UITableView. When I have retreived all web service data.
This is my sample code.
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
[UIApplication sharedApplication].networkActivityIndicatorVisible=YES;
NSError *err;
NSString *strResponse=[[NSString alloc]initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"response is %#",strResponse);
dit=[NSJSONSerialization JSONObjectWithData:responseData options:NSJSONReadingAllowFragments error:&err];
NSArray *arrResults = [dit valueForKey:#"classifieds_mst"];
listOfObjects = [NSMutableArray array];
for(dictRes in arrResults)
{
Attributes *at = [[Attributes alloc]init];
at.classimage=[dictRes valueForKey:#"image_name"];
[listOfObjects addObject:at];
}
[tableView reloadData];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *identifier=#"cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"identifier"];
}
classifiedimage=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 80)];
[cell.contentView addSubview:classifiedimage];
Attributes *att = [listOfObjects objectAtIndex:indexPath.row];
NSString *str;
str=att.classimage;
classifiedimage.image = [UIImage imageNamed:str];
return cell;
}
My requirement is i want to display images in uitableviewcells using json parser.I wrote the above code.But the images are not displayed in uitableviewcells.I want to use to display images in uitableviewcells using Asyncronous concept.Please give me any idea.I am new to the programming.Thanks in advance.
This is my json data.
{"classifieds_mst":[{"classified_id":83,image_name":"1389006378_butterfly.jpeg"},
{"classified_id":82,"image_name":"ttt.jpj"},{"classified_id":83,”image_name":"ttttt.jpj”}
imageNamed is used to load image from local bundle (in app).
imageWithData:dataWithURL is used to load images from url's.
You have to append domain name in your image name: (image_name":"1389006378_butterfly.jpeg), so that you can get URL of the image which is stored on server, now you can use below code:
[cell.yourImageView setImage:[UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:yourImageNameHere]]]];
By referring to your JSON data, it just contain the image_name only. So first of all, you need to build the actual image url. (copy paste that actual url in browser to make sure image is available in server).
Once you have the image url, then you can use AsyncImageView instead of UIImageView in your cell. It will handle the asynchronous thing for you as you just need to set the image url only. Thats the way to go.
One more suggestion is to recheck you cellForRowAtIndexPath, as the code always creating imageView's and adding to cell each time the cell is created. That's not required when you are reusing a cell. You just need to create the image view once when cell is allocated and just assign a tag to imageview and then get the imageview based on this tag and then use it. Just for your reference, I'm posting a sample code:
if(cell == nil){
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:#"identifier"];
AsyncImageView *imgView= [[[AsyncImageView alloc]init]autorelease];
imgView.tag = 1000;
imgView.contentMode = UIViewContentModeScaleAspectFill;
[cell.contentView addSubview:imgView];
}
AsyncImageView *imgView= (AsyncImageView*)[cell.contentView viewWithTag:1000];
contactImgView.frame = CGRectMake(0, 0, 300, 80);
//imgUrl is the actual url of image that is available in datasource
[contactImgView setImageURL:imgUrl];
Hope it is clear.
if you are using the AFNetworking then use it to download your image like
NSArray *keys = #[#"UserID", ];
NSArray *objects = #[#(userId)];
NSDictionary *parameter = [NSDictionary dictionaryWithObjects:objects forKeys:keys];
AFHTTPClient *httpClient = [[AFHTTPClient alloc] initWithBaseURL:
[NSURL URLWithString:BaseURLString]];
[httpClient setParameterEncoding:AFJSONParameterEncoding];
[httpClient registerHTTPOperationClass:[AFJSONRequestOperation class]];
NSMutableURLRequest *request = [httpClient requestWithMethod:#"POST"
path:#"UserService.svc/GetUserInfo"
parameters:parameter];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[httpClient registerHTTPOperationClass:[AFHTTPRequestOperation class]];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSError* error = nil;
id jsonObject = [NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingAllowFragments error:&error];
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
}];
[operation start];
and for image use this
[cell.userImage setImageWithURLRequest:[[NSURLRequest alloc] initWithURL:[NSURL URLWithString:userBasicInfo.imageUrl]]
placeholderImage:[UIImage imageNamed:#"facebook-no-user.png"]
success:^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image){
weakCell.userImage.image = image;
[weakCell setNeedsLayout];
} completion:^(BOOL success, NSError *error) {
NSLog(#"%#",[error localizedDescription]);
}];
}
failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error){
}];
You Create a subclass of UITableViewCell (can call it blogTableViewCell) for your cell and use that in the table.
Initialize blogTableViewCell with the JSON data (you could have an NSDictionary store the JSON info)
In blogTableViewCell create a function that loads image data on another thread (so the main thread can continue its course) and once the image is loaded, update the uiimageview on the cell to display it (This should be done on the main thread as it is a UI update)
- (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];
}
// Configure the cell...
//cell.textLabel.text = [[resultArray objectAtIndex:indexPath.row] valueForKey:#"name"];
cell.detailTextLabel.text = [[resultArray objectAtIndex:indexPath.row] valueForKey:#"designation"];
cell.imageView.image=[UIImage imageNamed:[[resultArray objectAtIndex:indexPath.row] valueForKey:#"image"]] ;
//[cell.imageView setImageWithURL:[NSURL URLWithString:[[resultArray objectAtIndex:indexPath.row] objectForKey:#"image"]]];
// NSURL *url = [NSURL URLWithString:[resultArray objectAtIndex:indexPath .row]];
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[[resultArray objectAtIndex:indexPath.row] valueForKey:#"image"] ]];
cell.imageView.image = [UIImage imageWithData:imageData];
return cell;
}
Related
I am new in iOS and I am facing problem regarding to show image in the Image View from Web Service.I am using code like this
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *STI=#"STI";
NewsTableViewCell *cell = (NewsTableViewCell *)[tableView dequeueReusableHeaderFooterViewWithIdentifier:STI];
if (cell == nil)
{
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:#"NewsTableViewCell" owner:self options:nil];
cell = [nib objectAtIndex:0];
cell.accessoryType=UITableViewCellAccessoryNone;
}
NSString *strImgURLAsString = [NewsImageArray objectAtIndex:indexPath.row];
[strImgURLAsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *imgURL = [NSURL URLWithString:strImgURLAsString];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:imgURL] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
img = [[UIImage alloc] initWithData:data];
if (img==nil) {
// img=[UIImage imageNamed:#"userimage.png"];
}
cell.newsimage.image=img;
// pass the img to your imageview
}else{
NSLog(#"%#",connectionError);
}
}];
cell.Headlbl.text=[NSString stringWithFormat:#"%#",[headarray objectAtIndex:indexPath.row]];
NSString *aux = [shortnamearray objectAtIndex:indexPath.row];
NSString * htmlString = #"<html><body>";
NSString *htmlString2=#"</body></html>";
NSString * NewString=[NSString stringWithFormat:#"%#%#%#",htmlString,aux,htmlString2];
NSAttributedString * attrStr = [[NSAttributedString alloc] initWithData:[NewString dataUsingEncoding:NSUnicodeStringEncoding] options:#{ NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType } documentAttributes:nil error:nil];
cell.bodylbl.attributedText=attrStr;
cell.bodylbl.textAlignment=NSTextAlignmentCenter;
cell.bodylbl.textColor=[UIColor whiteColor];
[cell.bodylbl setFont:[UIFont fontWithName:#"Arial" size:16]];
cell.backgroundColor = cell.contentView.backgroundColor;
// cell.bodylbl.text=[NSString stringWithFormat:#"%#",[shortnamearray objectAtIndex:indexPath.row]];
// cell.randrid.text=[NSString stringWithFormat:#"%#",[idarray objectAtIndex:indexPath.row]];
return cell;
}
Image Path - http://qaec.teams.in.net/UploadedFiles/Tommy Schaefer, of his role in the slaying, for which he is serving 18 year.png
http://qaec.teams.in.net/UploadedFiles/Tommy%20Schaefer,%20of%20his%20role%20in%20the%20slaying,%20for%20which%20he%20is%20serving%2018%20year.png
When Image Does not contain any gap it shows image
But when the Image contain any gap it not show image.How to solve this problem.Thanks in Advance!
You can use following method in UITableviewCell class. In your case add code in NewsTableViewCell.m When cell is created that time drowRect method is called. So in this method you need to set setClipsToBounds property of image view for which you setting the image to YES. This will solve your issue.
-(void)drawRect:(CGRect)rect
{
[super drawRect:rect];
self.profilePicImgView.layer.cornerRadius=self.profilePicImgView.frame.size.width/2;
[self.profilePicImgView setClipsToBounds:YES];
[self.profilePicImgView layoutIfNeeded];
[self.profilePicImgView setNeedsDisplay];
}
There is no need to use any other library etc. Your code is mistake on this line:
[strImgURLAsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
Have a look at this what does it do? Nothing. You should reassign the variable strImgURLAsString to this then it should work:
strImgURLAsString = [strImgURLAsString stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
For better performance, you can try this library called SDWebImage.
[imageView sd_setImageWithURL:[NSURL URLWithString:#"http://qaec.teams.in.net/UploadedFiles/Tommy%20Schaefer,%20of%20his%20role%20in%20the%20slaying,%20for%20which%20he%20is%20serving%2018%20year.png"] placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Also
You need to make sure that you have written this in your plist file
Use like this:
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:imgURL] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (!connectionError) {
dispatch_async(dispatch_get_main_queue(), ^{
img = [[UIImage alloc] initWithData:data];
if (img==nil) {
// img=[UIImage imageNamed:#"userimage.png"];
}
cell.newsimage.image=img;
// pass the img to your imageview
});
}else{
NSLog(#"%#",connectionError);
}
}];
I know it's good to idea to load image url in Imageview like the way you have written for better understanding of process. But maintaining cache is also important thing to consider. For better performance, I recommend you to use a very good library called SDWebImage. It helps you out in loading images faster with it's cache mechanism. Try this out. With this library it's this much simple.
[imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
Here is another one.
If you are using AFNetworking in your app, use below code to do that.
AFHTTPRequestOperation *requestOperation = [[AFHTTPRequestOperation alloc] initWithRequest:urlRequest];
requestOperation.responseSerializer = [AFImageResponseSerializer serializer];
[requestOperation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"Response: %#", responseObject);
_imageView.image = responseObject;
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(#"Image error: %#", error);
}];
[requestOperation start];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"cell";
TVcell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[TVcell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.titleLabel.text = [[[arrayData objectAtIndex:indexPath.row]valueForKey:#"title"]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
cell.txtlabel.text = [[[arrayData objectAtIndex:indexPath.row] valueForKey:#"description"]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
cell.tag = indexPath.row;
cell.imageView.image = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[enclosureUrlArray objectAtIndex:indexPath.row]]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.IMGLabel.image = image;
[cell setNeedsLayout];
}
});
}
});
return cell;
}
while i'm scrolling that same images are appearing on the cells,which cells im reusing.i used scroll view delegate also.im storing urls in enclosureUrlArray and i'm passing.
Put cell.IMGLabel.image = nil in your cellForRowAtIndexPath before downloading image, i.e. below cell.imageView.image = nil; this line.
Or set some place holder image (no image available kind of image to cell's image in interface builder), so if image is not downloaded then it will show this place holder image otherwise it will show downloaded image.
SDWebImage is good for this kind of case. It will cache the images so it will give better performance also. There is nothing wrong to use any good third party library.
By using SDWeb image:
#import <SDWebImage/UIImageView+WebCache.h>
...
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *MyIdentifier = #"MyIdentifier";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
reuseIdentifier:MyIdentifier] autorelease];
}
// Here we use the new provided sd_setImageWithURL: method to load the web image
[cell.imageView sd_setImageWithURL:[NSURL URLWithString:#"http://www.domain.com/path/to/image.jpg"]
placeholderImage:[UIImage imageNamed:#"placeholder.png"]];
cell.textLabel.text = #"My Text";
return cell;
}
You can also use NSURLSession as well,see this link
Async image loading from url inside a UITableView cell - image changes to wrong image while scrolling
NSURL *url = [NSURL URLWithString:[enclosureUrlArray objectAtIndex:indexPath.row]];
NSURLSessionTask *task = [[NSURLSession sharedSession] dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (data) {
UIImage *image = [UIImage imageWithData:data];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
MyCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
updateCell.IMGLabel.image = image;
});
}
}
}];
[task resume];
works perfect for me..
with the help of sdwebimage you can show the image like this:-
NSString *string2 = [[businessListArray objectAtIndex:indexPath.row ]valueForKey:#"logo"];
NSURL *url1 = [NSURL URLWithString:
[NSString stringWithFormat:
#"%#%#",
#"http://dev-demo.info.bh-in-15./upload/post/",
string2]];
UIImageView *imageView = (UIImageView *)[cell.contentView viewWithTag:301];
[imageView sd_setImageWithURL:url1
placeholderImage:[UIImage imageNamed:#"pocket.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
imageView.image = image;
}];
I making here simple application on XCODE 7.1. I just display 2 label and 1 image in tableview cell.I am parsing data from this URL. I am simply load data in TableviewHere i put the code of ViewController.m file
#interface ViewController ()
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIActivityIndicatorView *activityIndicator = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
activityIndicator.alpha = 1.0;
[self.view addSubview:activityIndicator];
activityIndicator.center = CGPointMake([[UIScreen mainScreen]bounds].size.width/2, [[UIScreen mainScreen]bounds].size.height/2);
[activityIndicator startAnimating];//to start animating
// Do any additional setup after loading the view, typically from a nib.
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:#"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
[activityIndicator stopAnimating];
_responsedic = (NSDictionary*) responseObject;
_Worldpopulation = [_responsedic valueForKey:#"worldpopulation"];
_imageURL = [_Worldpopulation valueForKey:#"flag"];
_country = [_Worldpopulation valueForKey:#"country"];
_population = [_Worldpopulation valueForKey:#"population"];
NSLog(#"Data:%#",_imageURL);
NSLog(#"Population",_population);
NSLog(#"Country",_country);
// NSLog(#"%#",_MovieList);
//NSLog(#"Array: %#",_imageURL);
//NSLog(#"%#",responseObject);
}
}];
[dataTask resume];
}
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return 10;
}
-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
NSString *Identifier = #"mycell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:Identifier];
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:Identifier];
// Set and load the images
[cell.imageView sd_setImageWithURL:[_imageURL objectAtIndex:indexPath.row] placeholderImage:nil completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
// Get rid of the activity indicator when the image has been loaded
}];
cell.textLabel.text = [_country objectAtIndex:indexPath.row];
cell.detailTextLabel.text = [_population objectAtIndex:indexPath.row];
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
//NSString *rowValue = self.friends[indexPath.row+1];
NSString *message = [[NSString alloc] initWithFormat:#"You selected %#",[_country objectAtIndex:indexPath.row]];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"YOU SELECT"
message:message
delegate:self
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
}
I am using AFNetworking 3.0 and SDWebImage for image loading.Data parse successfully and and displayed in tableview.I attached screenshot below
Problem is what the all data are not displayed in the tableview cell i also put the Alert dialog on each cell of tableview data successfully loaded but not displayed in cell. I search everywhere i can't find solution for this i am using 3G connection so net speed is not an issue Please someone help.
Try to reload table view with updated data in completion block.
NSURL *URL = [NSURL URLWithString:#"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDataTask *dataTask = [manager dataTaskWithRequest:request completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) {
if (error) {
NSLog(#"Error: %#", error);
} else {
[activityIndicator stopAnimating];
_responsedic = (NSDictionary*) responseObject;
_Worldpopulation = [_responsedic valueForKey:#"worldpopulation"];
_imageURL = [_Worldpopulation valueForKey:#"flag"];
_country = [_Worldpopulation valueForKey:#"country"];
_population = [_Worldpopulation valueForKey:#"population"];
NSLog(#"Data:%#",_imageURL);
NSLog(#"Population",_population);
NSLog(#"Country",_country);
// NSLog(#"%#",_MovieList);
//NSLog(#"Array: %#",_imageURL);
//NSLog(#"%#",responseObject);
//Added Code -> Reloading data on Main queue for update
dispatch_async(dispatch_get_main_queue(), ^{
[self.tableview reloadData];
});
}
}];
[dataTask resume];
Hope, it'll help you.
Thanks.
1) Parse Data and after getting data relaod table
-(void)ParseData
{
NSURLSession * session = [NSURLSession sharedSession];
NSURL * url = [NSURL URLWithString: #"http://www.androidbegin.com/tutorial/jsonparsetutorial.txt"];
//Create URLReques
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url
cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
[request addValue:#"application/x-www-form-urlencoded" forHTTPHeaderField:#"Content-Type"];
// Set Method POST/GET
[request setHTTPMethod:#"GET"];
// Asynchronously Api is hit here
NSURLSessionDataTask* dataTask=[session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) //If error nil
{
//Serialization data
NSDictionary * json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(#"json %#",json);
array=[json valueForKey:#"worldpopulation"];
dispatch_async(dispatch_get_main_queue(), ^(void) {
if(array.count!=0)
{
//Reload table View
[_tblView reloadData];
}
});
}
else
{
//failure;
}
}];
[dataTask resume] ; // Executed task
}
2) Table View DataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
if(array.count!=0)
{
return [array count];
}
return 0;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell;
//= [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
cell.backgroundColor =[UIColor whiteColor];
cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *lblCountry=(UILabel*)[cell viewWithTag:2];
lblCountry.text= [[array objectAtIndex:indexPath.row]valueForKey:#"country"];
UILabel *lblPopulation=(UILabel*)[cell viewWithTag:3];
lblPopulation.text= [[array objectAtIndex:indexPath.row]valueForKey:#"population"];
UIImageView *img = (UIImageView *)[cell viewWithTag:1];
[img setImageWithURL:[NSURL URLWithString:[[array objectAtIndex:indexPath.row]valueForKey:#"flag"]]];
return cell;
}
I wrote some code to get some data from a web service and load the data in a UITableView on the screen of my iOS objective-c app. I discovered that the UI freezes when I launch the app, and I'm sure it's because of call to web service JSON data in the viewDidload that's causing it. how do i make the process asynchronous? This is my code
// Calling the web service
NSURL *liveTunesURL = [NSURL URLWithString:#"http://api.radiome.org/tunes/realliveTunes"];
NSData *jsonData = [NSData dataWithContentsOfURL:liveTunesURL];
NSError *error = nil;
NSDictionary *dataDictionary = [NSJSONSerialization JSONObjectWithData:jsonData options:0 error:&error];
self.liveTunes = [NSMutableArray array];
NSArray *liveTunesArray = [dataDictionary objectForKey:#"Data"];
for (NSDictionary *liveTunesDictionary in liveTunesArray) {
LiveTunes *liveTune = [LiveTunes liveTunesWithChannel:[liveTunesDictionary objectForKey:#"channel"]];
liveTune.id = [liveTunesDictionary objectForKey:#"id"];
liveTune.channel = [liveTunesDictionary objectForKey:#"channel"];
liveTune.description = [liveTunesDictionary objectForKey:#"description"];
liveTune.urlPrefix = [liveTunesDictionary objectForKey:#"urlPrefix"];
liveTune.filename = [liveTunesDictionary objectForKey:#"filename"];
liveTune.url = [liveTunesDictionary objectForKey:#"url"];
liveTune.audio_stream = [liveTunesDictionary objectForKey:#"audio_stream"];
[self.liveTunes addObject:liveTune];
}
and here is part of my tableView data source code
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = #"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
LiveTunes *liveTune = [self.liveTunes objectAtIndex:indexPath.row];
if ([liveTune.url isKindOfClass:[NSString class]]) {
NSData *imageData = [NSData dataWithContentsOfURL:liveTune.thumbnailURL];
UIImage *image = [UIImage imageWithData:imageData];
cell.imageView.image = image;
}
else {
cell.imageView.image = [UIImage imageNamed:#"music_cell.png"];
}
cell.textLabel.text = liveTune.channel;
cell.detailTextLabel.text = liveTune.description;
return cell;
}
Can someone help me out to make the process Asynchronous so that the UI stops freezing.
Look in to using NSMutableURLRequest. Once you have a request object, use it like so.
AFHTTPRequestOperation *af = [[AFHTTPRequestOperation alloc] initWithRequest:request];
[af setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
//Success
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
//Failure
UIAlertController *confirmDialog =
[UIAlertController alertControllerWithTitle:#"Error"
message:[NSString stringWithFormat:#"Request Failed - Status %ld (%#)", (long)[operation.response statusCode], error.description]
preferredStyle:UIAlertControllerStyleAlert];
[confirmDialog addAction:[UIAlertAction actionWithTitle:#"Ok" style:UIAlertActionStyleDestructive handler:nil]];
[self presentViewController:confirmDialog animated:true completion:nil];
}];
[af start];
In the below code whenever I am scrolling the tableview, images in each cell are changing, which shouldn't happen. Please help. Thanks in advance.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UserDetails *userDetails = [arrUserDetails objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"CustomCell";
__weak TableViewCell *cell = (TableViewCell *)[_tableViewUsername dequeueReusableCellWithIdentifier:CellIdentifier];
cell.tag = indexPath.row;
cell.userName.text = userDetails.userName;
[self.operationQueue addOperationWithBlock: ^ {
NSURL *aURL = [NSURL URLWithString:userDetails.userImageURL];
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:aURL options:nil error:&error];
UIImage *image = nil;
if (cell.tag == indexPath.row)
{
image = [UIImage imageWithData:data];
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
cell.customImageView.image = image;
cell.customImageView.contentMode = UIViewContentModeScaleToFill;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}];
}
}];
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
UserDetails *userDetails = [arrUserDetails objectAtIndex:indexPath.row];
static NSString *CellIdentifier = #"CustomCell";
__weak TableViewCell *cell = (TableViewCell *)[_tableViewUsername dequeueReusableCellWithIdentifier:CellIdentifier];
cell.tag = indexPath.row;
cell.userName.text = userDetails.userName;
//Add Default placeholder
cell.customImageView.image = [UIImage imageNamed:#"Default.png"];
[self.operationQueue addOperationWithBlock: ^ {
NSURL *aURL = [NSURL URLWithString:userDetails.userImageURL];
NSError *error = nil;
NSData *data = [NSData dataWithContentsOfURL:aURL options:nil error:&error];
UIImage *image = nil;
if (cell.tag == indexPath.row)
{
image = [UIImage imageWithData:data];
[[NSOperationQueue mainQueue] addOperationWithBlock: ^ {
cell.customImageView.image = image;
cell.customImageView.contentMode = UIViewContentModeScaleToFill;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}];
}
}];
Add Default placeholder for image before loading it from url,As cells are being reused it takes the previous image
You can use SDWebImage.framework to load image
[cell.customImageView sd_setImageWithURL:[NSURL URLWithString:userDetails.userImageURL] placeholderImage:nil options:SDWebImageCacheMemoryOnly completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
if (image) {
[cell.customImageView setImage:image];
}
}];
You can use Afnetworking class for this .
Simply import #import "UIImageView+AFNetworking.h"
And use this line:-
[cell.imgProfile setImageWithURL:imgurl placeholderImage:[UIImage imageNamed:#""]];
Imgurl is the image Url which you are getting from response