asynchronous image downloading in tabelviewcell? - ios

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

Related

Async image loading from url inside a UITableView cell - image changes to wrong image while scrolling?

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ static NSString *CellIdentifier = #"cell";
TVcell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil)
cell = [[TVcell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.txtlabel.text = [[[arrayData objectAtIndex:indexPath.row] valueForKey:#"description"]stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceAndNewlineCharacterSet]];
cell.IMGLabel.contentMode = UIViewContentModeScaleAspectFill;
cell.IMGLabel.image = nil;
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:#"%#",[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(), ^{
cell.IMGLabel.image = image;
[cell.IMGLabel setImage:image];
[cell.IMGLabel.layer setMasksToBounds:YES];
[cell.IMGLabel.layer setCornerRadius:2.5f];
[cell setNeedsLayout];
});
}
}
}];
[task resume];
Your problem is that you have no guarantee that your NSUrlRequests will terminate in the same order than they started. This is bad because your cells are re-used for better performance and it can end with strange behavior.
You can find a fix here: Asynchronous downloading of images for UITableView with GCD
Or you can use tools listed here to help you address this issue: https://stackoverflow.com/a/32601838/3769338

First image in my array is not displayed in collectionview cell

- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
cell =[self.imgCllvw dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
if(!cell)
{
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
}
NSDictionary *tmpDict = [images objectAtIndex:indexPath.row];
NSURL *url = [NSURL URLWithString:[tmpDict objectForKey:#"img"]];
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0), ^{
NSData *data = [NSData dataWithContentsOfURL:url];
UIImage *imge= [[UIImage alloc]initWithData:data];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = imge;
});
});
cell.layer.borderWidth=1.0f;
cell.layer.borderColor=[UIColor colorWithRed:215.0/255.0 green:214.0/255.0 blue:214.0/255.0 alpha:1.0].CGColor;
return cell;
}
First image is not loaded and if I scroll the collectionview images are displayed and I have used autolayout for collectionview
I think you should try async downloading of image rather than sync, something like this
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
cell =[self.imgCllvw dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
if(!cell)
{
cell = [collectionView dequeueReusableCellWithReuseIdentifier:#"Cell" forIndexPath:indexPath];
}
NSDictionary *tmpDict = [images objectAtIndex:indexPath.row];
NSURL *url = [NSURL URLWithString:[tmpDict objectForKey:#"img"]];
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 *cell = (id)[collectionView cellForItemAtIndexPath:indexPath];
if (cell)
cell.imageView.image = image;
});
}
}
}];
[task resume];
cell.layer.borderWidth=1.0f;
cell.layer.borderColor=[UIColor colorWithRed:215.0/255.0 green:214.0/255.0 blue:214.0/255.0 alpha:1.0].CGColor;
return cell;
}
Instead of dispatch_async, mainqueue you can use dispatch_sync, like this,
dispatch_sync(dispatch_get_main_queue(), ^{
cell.imageView.image = imge;
});

Images in cell are changing everytime when tableview is scrolled

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

I can't get image from PFFile

Parse.com just updated their SDKs to support local storage. But after installing new SDKs I have occurred some problems with PFFile. I have used the same method for a long time, but now that I'm using the new SDK I can't get it to work.
Here's my code:
.h file
#property (strong, nonatomic) IBOutlet PFFile *iconPhoto;
.m file
cell.iconPhoto.image = [UIImage imageNamed:#"placeholder.png"]; // placeholder image
cell.iconPhoto.file = (PFFile *)object[#"icon"]; // remote image
[cell.iconPhoto loadInBackground:^(UIImage *image, NSError *error) {
cell.iconPhoto.image = image;
cell.userInteractionEnabled = YES;
}];
When I run, I get these errors (link)
Is someone else having the same problems?
UPDATE:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
static NSString *CellIdentifier = #"Cell";
MainTVCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
PFObject *object = [self.currentCategories objectAtIndex:indexPath.row];
cell.mainLabel.text = object[#"name"];
cell.userInteractionEnabled = YES;
if (![object[#"icon"] isEqual:[NSNull null]]) {
cell.image = [UIImage imageNamed:#"loading.png"]; // placeholder image
cell.iconPhoto = (PFFile *)object[#"icon"]; // remote image
[cell.iconPhoto getDataInBackgroundWithBlock:^(NSData *imageData, NSError *error) {
if (!error && imageData) {
cell.image = [UIImage imageWithData:imageData];
cell.userInteractionEnabled = YES;
}
}];
}
return cell;
}
I found a solution myself.
PFFile *file = (PFFile *)object[#"icon"];
[file getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
cell.iconImageView.image = [UIImage imageNamed:#"placeholder.png"]; // placeholder image
cell.iconImageView.image = [UIImage imageWithData:data];
cell.userInteractionEnabled = YES;
}];
This will load the images.
Weird thing it won't run in the simulator.. But works perfectly on iPhone.

how to loading images using Asynchronous GCD For UITableviewcell/

I'm loading images for my uitableview asynchronously using GCD, but there is a problem - when scrolling down UITableview the images are dissappeared on top.And sometimes the images are not displayed in UITableviewcell. This is my code.please give me any idea.Is there any error in my code.Please help me.
- (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"];
}
image=[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 80)];
[cell.contentView addSubview:image];
str=att.classimage;
url=#"My URL";
if(str!=nil){
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
dispatch_async(dispatch_get_main_queue(), ^{
NSString *imageStr=[url stringByAppendingString:str];
image.image = [UIImage imageNamed:imageStr];
});
});
image.image=[UIImage imageNamed:#"nav-bar-logo.png"];
}
return cell;
}
Before setting Image check if that cell is still in memory.
UITableViewCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
{
yourImageView.image = [imagePost fixOrientation];
}
I am doing similar thing, but Using NSURLConnection.
NSURL *postImage = [NSURL URLWithString:#"Your URL"];
NSMutableURLRequest *imageRequest = [[NSMutableURLRequest alloc]initWithURL:postImage cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30];
[imageRequest setHTTPMethod:#"GET"];
[NSURLConnection sendAsynchronousRequest:imageRequest queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error)
{
imagePost = [UIImage imageWithData:data]; // UIImage Object
UITableViewCell *updateCell = (id)[tableView cellForRowAtIndexPath:indexPath];
if (updateCell)
{
postImageView.image = [imagePost fixOrientation];// setting my ImageView
}
}];
Hope this will help you.
You can use AFNetworknig for showing images from remote URL.
get AFNetworking from here
just
#import "AFNetworking.h"
[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:#"placeHolderImage"]];
- (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];
UIImageView *imageView =[[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 300, 80)];
imageView.tag = 100;
[cell.contentView addSubview:imageView];
}
str=att.classimage;
url=#"My URL";
UIImageView *cellImageView = [cell.contentView viewWithTag:100];
cellImageView.image = nil;
if(str!=nil) {
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
NSString *imageStr = [url stringByAppendingString:str];
UIImage *image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageStr]]];
dispatch_async(dispatch_get_main_queue(), ^{
cellImageView.image = image;
});
});
}
return cell;
}

Resources