Images in cell are changing everytime when tableview is scrolled - ios

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

Related

asynchronous image downloading in tabelviewcell?

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

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

Display time taken to download image from url and display in customtablecell

Here is my code, please help. In the below I need to get the time taken to load image from url and display the time in custom tableview cell. Which we can use either NSTimer or NSDate.
Thanks in advance.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
TableViewCell *cell = (TableViewCell *)[_tableViewUsername dequeueReusableCellWithIdentifier:CellIdentifier];
NSDate *object = arrURL[indexPath.row];
rowCount = indexPath.row;
cell.userName.text = [arrUserNames objectAtIndex:indexPath.row];
if ([object valueForKey:#"status"])
{
if([[object valueForKey:#"status"]isEqualToString:#"completed"] && [object valueForKey: #"image"] && [[object valueForKey: #"image"] isKindOfClass:[UIImage class]])
{
cell.customImageView.contentMode = UIViewContentModeScaleToFill;
cell.customImageView.image = [object valueForKey:#"image" ];
cell.accessoryType = UITableViewCellAccessoryCheckmark;
}
}
else
{
[object setValue:#"inprogress" forKey:#"status"];
[self.operationQueue addOperationWithBlock:^
{
UIImage * image = [UIImage imageWithData:[NSData dataWithContentsOfURL:
[NSURL URLWithString:[object valueForKey:#"url"]]]];
[object setValue:image forKey:#"image"];
[object setValue:#"completed" forKey:#"status"];
//count set
[[NSOperationQueue mainQueue] addOperationWithBlock:^
{
[_tableViewUsername reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
}];
}];
}
return cell;
}
You can use following code. But for this you have to use SDWebImageCache
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:#"cellId"];
__block NSDate *startTime = [NSDate date];
[cell.nImageView sd_setImageWithURL:[NSURL URLWithString:[imageUrlArray objectAtIndex:indexPath.row]] completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType, NSURL *imageURL) {
NSDate *endTime = [NSDate date];
NSTimeInterval secs = [endTime timeIntervalSinceDate:startTime];
NSLog(#"Seconds (%ld) --------> %f",(long)indexPath.row, secs);
}];
return cell;
}
To download SDWebImage Use this link
Define below method in your .m file
- (void)downloadImageFrom:(NSString *)strURL response:(void (^)(NSData *data))handler
{
strURL = [strURL stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:strURL]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data)
{
handler(data);
}
}];
}
And call from cellForRowAtIndexpath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = #"CustomCell";
TableViewCell *cell = (TableViewCell *)[_tableViewUsername dequeueReusableCellWithIdentifier:CellIdentifier];
NSDate *object = arrURL[indexPath.row];
rowCount = indexPath.row;
cell.userName.text = [arrUserNames objectAtIndex:indexPath.row];
cell.customImageView.contentMode = UIViewContentModeScaleToFill;
cell.accessoryType = UITableViewCellAccessoryCheckmark;
[self downloadImageFrom:[object valueForKey:#"url"] response:^(NSData *data) {
if (data)
{
cell.customImageView.image = [[UIImage alloc] initWithData:data];
}
}];
}

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