Objective - C: UITableView Content Changing on Scroll - ios

I'm using the QuickBlox Framework to build a chatting application. Currently, when the chat view opens up, everything looks great.
However, when the users begins to scroll up and down the chat history, some of the cells begin to change (for example, they'll show an image which should be placed in a different row).
Below is my code for cellForRowAtIndexPath, if anyone can tell me what I'm doing wrong
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
QBChatMessage *message = [[ChatService shared] messagsForDialogId:self.dialog.ID][indexPath.row];
if (message.attachments.count > 0) {
ImageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ImageCellIdentifier];
[cell configureCellWithImage:message];
cell.backgroundColor = [UIColor whiteColor];
return cell;
} else {
ChatMessageTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:ChatMessageCellIdentifier];
[cell configureCellWithMessage:message];
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
}
EDIT Please see below my ImageTableViewCell configureCellWithImage method:
- (void) configureCellWithImage:(QBChatMessage*)message {
NSString *time = [message.dateSent timeAgoSinceNow];
if ([QBSession currentSession].currentUser.ID == message.senderID) {
// Message was sent by me
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
// image is already downloaded
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
UIImageView *cellImage = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectMake(320-155, 10, 140, 140)];
cellImage.frame = CGRectMake(7, 7, 120, 120);
[cellImage setContentMode:UIViewContentModeScaleAspectFill];
cellImage.clipsToBounds = YES;
cellImage.layer.cornerRadius = 5;
cellImage.image = image;
self.backgroundImageView.image = aquaBubble;
[self.backgroundImageView addSubview:cellImage];
[self.contentView addSubview:self.backgroundImageView];
});
} else {
// downloads the image and displays as above
}
} else {
// Message was sent by another user
NSData *imageData = [FTWCache objectForKey:[NSString stringWithFormat:#"%#", [message.attachments[0] valueForKey:#"ID"]]];
if (imageData) {
dispatch_async(dispatch_get_main_queue(), ^{
UIImage *image = [UIImage imageWithData:imageData];
UIImageView *cellImage = [[UIImageView alloc] init];
[self.backgroundImageView setFrame:CGRectMake(padding/2, padding+5, 140, 140)];
cellImage.frame = CGRectMake(13, 7, 120, 120);
[cellImage setContentMode:UIViewContentModeScaleAspectFill];
cellImage.layer.cornerRadius = 5;
cellImage.clipsToBounds = YES;
cellImage.image = image;
self.timeLabel.frame = CGRectMake(20, self.backgroundImageView.frame.size.height + 20, 80, 20);
self.timeLabel.text = [NSString stringWithFormat:#"%#", time];
[self.timeLabel setFont:[UIFont systemFontOfSize:10.0]];
[self.timeLabel setTextColor:[UIColor blackColor]];
[self.contentView addSubview:self.timeLabel];
self.nameAndDateLabel.textAlignment = NSTextAlignmentLeft;
QBUUser *sender = [ChatService shared].usersAsDictionary[#(message.senderID)];
NSInteger loginForColor = [sender.login integerValue];
loginForColor = loginForColor % 255;
self.nameAndDateLabel.text = [NSString stringWithFormat:#"%#", sender.fullName];
self.backgroundImageView.image = orangeBubble;
[self.backgroundImageView addSubview:cellImage];
[self.contentView addSubview:self.backgroundImageView];
});
} else {
// downloads the image and displays as above
}
}
}

Cells get reused. Therefore you must always set/reset all properties of the cell each time.
For every if statement that sets a cell's property, there must be an else statement that resets the same property - even if it just clears the value.
Also you must avoid adding subviews over and over each time the cell is used. You have code that creates and adds an image view to the cell. But you keep adding new image views over and over. Just add it once if needed. If it's already there, update it with the new image instead of adding a new one.

The error should be on the functions configureCellWithImage and configureCellWithMessage.
I didn't see the code of those functions, but i bet that you didn't clean the image content on the configureCellWithMessage.

Related

How to make smooth UITableView in objective-C [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I am working with an IOS application. In my project have several UITableView with many rows, and each row has two images. When I scroll fast then It can't load cells smoothly. How can I scroll smoothly ???
N.B: I don't want to load all rows at a time.
Please Help
Edited:
Here is my code :
-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell;
float sca=appDelegate.deviceScaleFloat;
float XOffset=0*sca;
cell = [[UITableViewCell alloc] init];
cell.opaque = YES;
cell.selectionStyle = UITableViewCellSelectionStyleNone;
UIImage *backImg;
backImg= [UIImage imageNamed:[NSString stringWithFormat:#"background-goal-collect%#.png",ipadExtention]];
backImg=[self scaleWithScaleFactor:backImg];
UIImageView *btnBuyImageView=[[UIImageView alloc]initWithImage:backImg];
btnBuyImageView.frame=CGRectMake(XOffset, 0, backImg.size.width, backImg.size.height);
[cell.contentView addSubview: btnBuyImageView];
for (int i=0; i<5 && indexPath.row*5+i<[catFishes count]; i++) {
int productIndex = (int)indexPath.row*5 + i;
DBProductAttributes *productAttributes = [allProductAttributes objectAtIndex:productIndex];
DBProductInfo *productInfo = [catFishes objectAtIndex:productIndex];
UIImage *frameImage = [UIImage imageNamed:[NSString stringWithFormat:#"background-element-%d%#.png",productAttributes.elementid,ipadExtention]];
frameImage=[self scaleWithScaleFactor:frameImage];UIImageView *frameView = [[UIImageView alloc] initWithImage:frameImage];
frameView.frame = CGRectMake((frameImage.size.width*i)+10*sca+5*i*sca, 5*sca , frameImage.size.width, frameImage.size.height);
frameView.userInteractionEnabled=YES;
[cell.contentView addSubview:frameView];
MyTapGestureRecognizer *tapGesture=[[MyTapGestureRecognizer alloc] init];
tapGesture.tag=productIndex;
[tapGesture addTarget:self action:#selector(buttonClicked:)];
[frameView addGestureRecognizer:tapGesture];
NSString *IconStr = [NSString stringWithFormat:#"i%db.png", productInfo.productid];
UIImage *btnImg = [UIImage imageNamed:IconStr];
if(![self isProductPurchesed:productInfo.productid])
{
if([ITIWAppDelegate blackimageforstore]>0)
{
btnImg = [self getBlackAndWhiteVersionOfImage:btnImg];
}
}
UIImageView *imageIconView;
imageIconView = [[UIImageView alloc] initWithImage:btnImg];
imageIconView.frame = CGRectMake(frameView.frame.origin.x+frameImage.size.width-64*sca, frameView.frame.origin.y/*+frameImage.size.height-64*sca*/ , 64*sca, 64*sca);
imageIconView.opaque = YES;
[cell.contentView addSubview:imageIconView];
UILabel *name;
name = [[UILabel alloc] initWithFrame:CGRectMake(frameView.frame.origin.x, frameView.frame.origin.y+62*sca, frameImage.size.width-0*sca, 18.0f*sca)];
name.text = productInfo.product_name;
name.font = [UIFont fontWithName:#"Georgia" size:12.0f*sca];
name.adjustsFontSizeToFitWidth = YES;
name.textAlignment = NSTextAlignmentCenter;
if(![self isProductPurchesed:productInfo.productid])
name.backgroundColor=[UIColor grayColor];
else
name.backgroundColor = [UIColor colorWithRed:colorCodeDragonBook[productAttributes.elementid-1][0]/255.0f green:colorCodeDragonBook[productAttributes.elementid-1][1]/255.0f blue:colorCodeDragonBook[productAttributes.elementid-1][2]/255.0f alpha:1.0f];
name.textColor = [UIColor colorWithWhite:1.0 alpha:1.0];
//name.shadowColor = [UIColor blackColor];
name.autoresizingMask = UIViewAutoresizingFlexibleRightMargin;
[cell.contentView addSubview:name];
NSArray *otherElements = [productAttributes.otherElementid componentsSeparatedByString:#","];
int k=0;
UIImage *habitatFlag = [UIImage imageNamed:[NSString stringWithFormat:#"flag-%d.png",productAttributes.elementid]]; UIImageView *habitatFlagView = [[UIImageView alloc] initWithImage:habitatFlag];
habitatFlagView.frame = CGRectMake(frameView.frame.origin.x-1*sca, frameView.frame.origin.y-1*sca , 15*sca, 22*sca);
[cell.contentView addSubview:habitatFlagView];
k+=15;
for (int i=0; i<[otherElements count]; i++) {
int otherElementid = [[otherElements objectAtIndex:i] intValue];
if(otherElementid==productAttributes.elementid) continue;
UIImage *habitatFlag = [UIImage imageNamed:[NSString stringWithFormat:#"flag-%d.png",otherElementid]]; UIImageView *habitatFlagView = [[UIImageView alloc] initWithImage:habitatFlag];
habitatFlagView.frame = CGRectMake(frameView.frame.origin.x+k*sca-1*sca, frameView.frame.origin.y-1*sca , 15*sca, 22*sca);
[cell.contentView addSubview:habitatFlagView];
k+=15;
}
}
return cell;
}
Problem is occurring when the cells are going to off screen, the tableview release all cells of off screen. And when after that I want to scroll the cells are reloading. I think it is not optimal to load cells. But I don't know how to optimize this.
the best you have to do is load the images asynchronously, and not in the main thread.
If you want, you can use my ImageLoader project : https://github.com/celian-m/ImageLoader/blob/master/ImageLoader.swift
All you have to do is using CMImageView instead of UIImageView.
Then you can do [myImageView assignImageFromUrl:YOUR_URL]
This will load your images in the background thread, in FIFO mode, and save it in memory and disk cache ( i.e. : you need to load each image only 1 time ).
You can make use of SDWebImageCache so that it'll cache the images in disk and the loading of images becomes much faster.
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0ul);
dispatch_async(queue, ^{
//set image here
});
What about setting the image async in the tableview callback:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
May I ask whether the images are web images or local images?

Image is getting added automatically in UItableView Cell?

Helo all,
I am having a very strange situation here.I have a table view in which i have custom cells. So i have designed my own custom cell.In custom cell i am displaying the image as well text.The data of table comes from server.If any image in json then image will be displayed else only text is displayed.So cell will dynamic.I have used bezier path to wrap text around image.No if image is there so text will be wrapped.When i add new post from server with image & i refresh the table then it automatically display the image for other post as well.It will display the same image which is same image for last.I don;t know why new cell is adding image in it's cell even the code works fine i have dbugged it using breakpoints.Please tell what could be the issue.
Here is code for cellForRowAtIndexPath
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
//define variables here
static NSString *CellIdentifier = #"homeCell";
HomeCell *cell = [tableView
dequeueReusableCellWithIdentifier:CellIdentifier
forIndexPath:indexPath];
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
if([arr_post count]>0)
{
NSMutableAttributedString *mutableAttributeStr;
NSAttributedString *attributeStr;
[cell layoutIfNeeded];
//get the post data
Post *user_post=[arr_post objectAtIndex:indexPath.row];
//set the button tags
cell.btn_like.tag=indexPath.row;
cell.btn_comment.tag=indexPath.row;
cell.btn_fav.tag=indexPath.row;
cell.btn_con.tag=indexPath.row;
cell.btn_book.tag=indexPath.row;
//add info to buttons
cell.btn_like.selected=user_post.isPostLiked;
cell.btn_comment.selected=user_post.isPostCommented;
cell.btn_fav.selected=user_post.isPostFavourite;
cell.btn_con.selected=user_post.isPostCondolence;
cell.btn_book.selected=user_post.isPostBookmarked;
//add user info
cell.label_name.text=user_post.username;
cell.img_profile.layer.cornerRadius = 25;
cell.img_profile.clipsToBounds = YES;
[cell.img_profile setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.user_profileImage]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
//add location
if([user_post.location isEqualToString:#"Not Available"])
{
[cell.img_icon_location setHidden:true];
[cell.label_location setHidden:true];
}
else
{
[cell.img_icon_location setHidden:false];
[cell.label_location setHidden:false];
cell.label_location.text=user_post.location;
}
//ad post info
cell.tv_post.text=user_post.post_description;
cell.tv_post.font = [UIFont fontWithName:user_post.font_family size:[user_post.font_size floatValue]];
[cell.tv_post setTextColor:[self colorFromHexString:user_post.font_color]];
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *date = [formatter dateFromString:user_post.modification_date];
NSLog(#"user post image is %#",user_post.post_image);
if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
{
NSLog(#"NOT INSIDE THE CONDITION");
}
else
{
NSLog(#"INSIDE BEIZER PATH CONDITION");
UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(0, 10, 100, 100)];
cell.tv_post.textContainer.exclusionPaths = #[imgRect];
UIImageView *tv_image =[[UIImageView alloc]initWithFrame:CGRectMake(0, 10, 100, 100)];
if(![user_post.post_image isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_image]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
if(![user_post.post_video isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_video_thumbnail]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
[cell.tv_post addSubview:tv_image];
}
//make textview height dynamic
cell.tv_post.scrollEnabled=NO;
if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
{
CGFloat fixedWidth = cell.tv_post.frame.size.width;
CGSize newSize = [cell.tv_post sizeThatFits:CGSizeMake(fixedWidth, MAXFLOAT)];
CGRect newFrame = cell.tv_post.frame;
newFrame.size = CGSizeMake(fmaxf(newSize.width, fixedWidth), newSize.height);
cell.tv_post.frame = newFrame;
cell.tv_height.constant=cell.tv_post.frame.size.height;
[cell.view_tvContainer layoutIfNeeded];
}
//set the border of uiview
cell.view_tvContainer.layer.borderColor = [UIColor blackColor].CGColor;
cell.view_tvContainer.layer.borderWidth = 2.0f;
//set the like count
NSString *first_like_user=recent_like_name=user_post.recent_like_name;
NSLog(#"FIRST LIEK USER IS %#",first_like_user);
NSString *str_recent_like_name;
int count=(int)[first_like_user length];
int like_count=[user_post.like_count intValue];
if(like_count>0)
{
cell.label_like_count.lineBreakMode=NSLineBreakByWordWrapping;
[cell.label_like_count sizeToFit];
[cell.label_like_count setHidden:false];
NSString *str_like_count=[NSString stringWithFormat:#"%lu",(unsigned long)like_count-1];
if(like_count==1)
{
if([myUsername isEqualToString:first_like_user])
{
first_like_user=#"You like this post ";
count=3;
}
else
{
first_like_user=[first_like_user stringByAppendingString:#" like this post"];
}
}
else if(like_count==2)
{
if([first_like_user isEqualToString:myUsername])
{
first_like_user=#"You";
}
Post *temp_user_post=[copy_arr_user_post objectAtIndex:indexPath.row];
first_like_user=[first_like_user stringByAppendingString:#" and "];
if(temp_user_post.recent_like_name==nil)
{
temp_user_post.recent_like_name=#"";
}
str_recent_like_name=[temp_user_post.recent_like_name_two stringByAppendingString:#" like this post"];
first_like_user=[first_like_user stringByAppendingString:str_recent_like_name];
}
else
{
if(like_count>1000)
{
like_count=like_count/1000;
str_like_count=[NSString stringWithFormat:#"%lu",(unsigned long)like_count];
str_like_count=[str_like_count stringByAppendingString:#"k"];
first_like_user=[first_like_user stringByAppendingString:#" and "];
str_like_count=[str_like_count stringByAppendingString:#" others like this post"];
first_like_user=[first_like_user stringByAppendingString:str_like_count];
}
else
{
if([first_like_user isEqualToString:myUsername])
{
first_like_user=#"You";
}
first_like_user=[first_like_user stringByAppendingString:#" and "];
str_like_count=[str_like_count stringByAppendingString:#" others like this post"];
first_like_user=[first_like_user stringByAppendingString:str_like_count];
}
}
mutableAttributeStr = [[NSMutableAttributedString alloc]initWithString:first_like_user];
attributeStr = [[NSAttributedString alloc]initWithString:#"\n" attributes:#{NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue-Bold" size:8]}];
[mutableAttributeStr addAttribute:NSFontAttributeName value: [UIFont fontWithName:#"Helvetica-Bold" size:14.0] range:NSMakeRange(0, count)];
[mutableAttributeStr addAttribute:NSForegroundColorAttributeName value:[self colorFromHexString:#"#48a0dd"] range:NSMakeRange(0, count)];
[mutableAttributeStr appendAttributedString:attributeStr];
[cell.label_like_count setAttributedText:mutableAttributeStr];
}
else
{
[cell.label_like_count setHidden:true];
}
// show dynamic comment
NSMutableArray *user_comments=user_post.comments;
float comment_count=[user_post.comment_count intValue];
NSLog(#"ID IS %#",user_post.id);
if(comment_count>0)
{
//make label multiline
cell.first_comment.lineBreakMode=NSLineBreakByWordWrapping;
[cell.first_comment sizeToFit];
cell.second_cmment.lineBreakMode=NSLineBreakByWordWrapping;
[cell.second_cmment sizeToFit];
cell.third_comment.lineBreakMode=NSLineBreakByWordWrapping;
[cell.third_comment sizeToFit];
if(comment_count==1)
{
[cell.first_comment setHidden:false];
[cell.second_cmment setHidden:true];
[cell.third_comment setHidden:true];
}
else if(comment_count==2)
{
[cell.first_comment setHidden:false];
[cell.second_cmment setHidden:false];
[cell.third_comment setHidden:true];
}
else
{
[cell.first_comment setHidden:false];
[cell.second_cmment setHidden:false];
[cell.third_comment setHidden:false];
[cell.btn_more_comments setHidden:false];
}
for(l=0;l<[user_comments count];l++)
{
Comment *comment=[user_comments objectAtIndex:l];
NSString *comment_string=[comment.user_name stringByAppendingString:#" "];
comment_string=[comment_string stringByAppendingString:comment.comment];
int count=(int)[comment.user_name length];
NSMutableAttributedString* mutableAttributeStr = [[NSMutableAttributedString alloc]initWithString:comment_string];
NSAttributedString *attributeStr = [[NSAttributedString alloc]initWithString:#"\n" attributes:#{NSFontAttributeName : [UIFont fontWithName:#"HelveticaNeue-Bold" size:8]}];
[mutableAttributeStr addAttribute:NSFontAttributeName value: [UIFont fontWithName:#"Helvetica-Bold" size:14.0] range:NSMakeRange(0, count)];
[mutableAttributeStr addAttribute:NSForegroundColorAttributeName value:[self colorFromHexString:#"#48a0dd"] range:NSMakeRange(0, count)];
[mutableAttributeStr appendAttributedString:attributeStr];
// end of the repetitive pattern
if (l == 0)
{
[cell.first_comment setAttributedText:mutableAttributeStr];
}
else if (l == 1)
{
[cell.second_cmment setAttributedText:mutableAttributeStr];
}
else if (l == 2)
{
[cell.third_comment setAttributedText:mutableAttributeStr];
}
}
}
else
{
[cell.first_comment setHidden:true];
[cell.second_cmment setHidden:true];
[cell.third_comment setHidden:true];
[cell.btn_more_comments removeFromSuperview];
}
cell.label_time.text=[BaseController timeAgoStringFromDate:date];
[arr_indexpath addObject:indexPath];
}
return cell;
}
Keep in mind that the cells is reused. If you have, say, 10000 rows in your table datasource, the table view won't create that many rows. It will only create enough rows to be displayed on the screen and a few others to be preloaded.
For every time you scroll your table, the tableview will use those cells that go invisible to load the new cells that just become visible, to make a illusion of infinite amount of rows. That why those new cells have the old data. So basically, you will have to set your UIImageView's image to nil in cellForRowAtIndexpath: if no image is available.
if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
{
NSLog(#"NOT INSIDE THE CONDITION");
}
In the code of you above, you simply print out a log, while what you also have to do is setting the UIImageView's image to nil.
So this is my suggestion:
//if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
//{
// NSLog(#"NOT INSIDE THE CONDITION");
//}
//else
{
NSLog(#"INSIDE BEIZER PATH CONDITION");
UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(0, 10, 100, 100)];
cell.tv_post.textContainer.exclusionPaths = #[imgRect];
UIImageView *tv_image =[[UIImageView alloc]initWithFrame:CGRectMake(0, 10, 100, 100)];
if(![user_post.post_image isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_image]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
else{
[tv_image setImage:nil]; //Prevent the old data to be shown
}
if(![user_post.post_video isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_video_thumbnail]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
else{
[tv_image setImage:nil];//Prevent the old data to be shown
}
[cell.tv_post addSubview:tv_image];
}
Maybe this code doesn't fit your requirements about how the data will be displayed, but hope it helps you to get the idea!
When a tableview cell is needed to be displayed you will either create a new one or reuse one that you created previously but is no longer visible on screen. Since you have created a UIImageView and added it to a cell, when you reuse it the image is still there.
To stop this happening, you need to keep a reference to the imageview so the next time around you are able to remove it. Since you are adding them dynamically and don't have an IBOutlet your quickest option is to assign the image a tag
UIImageView *tv_image =[[UIImageView alloc]initWithFrame:CGRectMake(0, 10, 100, 100)];
tv_image.tag = 21; // arbitrary number but must be unique to the image
By tagging the image, the next time around you can get access to it:
UIImageView *tv_image = (UIImageView*)[cell viewWithTag:21];
if (tv_image != nil) {
tv_image.image = nil; // remove the image (or remove the image view from the cell etc)
}
Just be sure to refactor the code accordingly so that if you find the image from a tag you don't need to recreate it etc
Your img_profile is getting repeated because your are re-using the cell.
Replace the below line of code
[cell.img_profile setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.user_profileImage]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
with below code:-
if (user_post.user_profileImage.length == 0) {
cell.img_profile.hidden = true;
}else{
[cell.img_profile setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.user_profileImage]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
Explanation:-
Check if your json contains the user profile image then set the image, else hide the profile image view.
A table view reuses cells. This means that if you add a subview to a cell, as you do on the line [cell.tv_post addSubview:tv_image], then that subview will still be in the cell when it is reused.
Basically, if you are adding subviews to a custom cell in tableView:cellForRowAtIndexPath:, you are probably making a mistake.
Just design the tv_image view into the HomeCell in the first place. HomeView should have an outlet named tv_image, connected to the image view in your storyboard or XIB. When you need tv_image, show it. Otherwise, hide it.
if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
{
NSLog(#"NOT INSIDE THE CONDITION");
cell.tv_image.image = nil;
cell.tv_image.hidden = YES;
cell.tv_post.textContainer.exclusionPaths = #[];
}
else
{
NSLog(#"INSIDE BEIZER PATH CONDITION");
UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(0, 10, 100, 100)];
cell.tv_post.textContainer.exclusionPaths = #[imgRect];
if(![user_post.post_image isEqualToString:#"none"])
{
[cell.tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_image]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
if(![user_post.post_video isEqualToString:#"none"])
{
[cell.tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_video_thumbnail]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
cell.tv_image.hidden = NO;
}
Also, make sure setImageWithURL:placeholderImage: doesn't set the image view's hidden = NO when it loads the image.
I wonder where you are allocating you custom cell. Shouldn't you be creating cell only if it's not created. Something like this:
static NSString *CellIdentifier = #"homeCell";
HomeCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(!cell)
{
cell = [[[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]];
}
And then updating the UI components.
if([user_post.post_image isEqualToString:#"none"] && [user_post.post_video isEqualToString:#"none"])
{
NSLog(#"NOT INSIDE THE CONDITION");
}
else
{
NSLog(#"INSIDE BEIZER PATH CONDITION");
UIBezierPath * imgRect = [UIBezierPath bezierPathWithRect:CGRectMake(0, 10, 100, 100)];
cell.tv_post.textContainer.exclusionPaths = #[imgRect];
UIImageView *tv_image =[[UIImageView alloc]initWithFrame:CGRectMake(0, 10, 100, 100)];
if(![user_post.post_image isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_image]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
if(![user_post.post_video isEqualToString:#"none"])
{
[tv_image setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.post_video_thumbnail]]placeholderImage:[UIImage imageNamed:#"post_placeholder.png"]];
}
[cell.tv_post addSubview:tv_image];
}
perhaps you should write an "update method" inside your "HomeCell" class. To update the UI components.
I recommend to use [SDWebImage][1]https://github.com/rs/SDWebImage , where you can update your cell in completion block or cache image if need
The problem is two folds:
cells are reused, this is common place for miss, but not in your case.
your line [cell.img_profile setImageWithURL:...]; is asynchronous, which mean by the time the image is downloaded, your cell may be reused, so clearing the imageView at reuse won't help.
To properly use async-loading of image in a reusable cell, you have to double check that it's the correct image on loading success.
add a property to the cell class:
#property (weak) NSURL *targetImageUrl;
then change the loading to add a check:
NSURL *targetImageUrl = [NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.user_profileImage]];
cell.targetImageUrl = targetImageUrl; // <!> replace latest target
[cell.img_profile
setImageWithURLRequest: [NSMutableURLRequest requestWithURL:targetImageUrl]
placeholderImage: [UIImage imageNamed:#"post_placeholder.png"]
success: ^(NSURLRequest *request, NSHTTPURLResponse *response, UIImage *image) {
if (cell.targetImageUrl != targetImageUrl) return; // <!> this is the trick
cell.img_profile.image = image;
}
failure: ^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
}];
Since the cellForRowAtIndexPath is called whenever the cell becomes visible, I always use the next strategy for displaying images that need to be loaded from the web: I either associate the image (when downloaded) with objc_setAssociatedObject with the object that contains data for table row, or create some hashMap where i put the images with some id for the key. Then in cellForRowAtIndexPath I check if associated object is nil (or if image for the key exists in hashmap). If it's nil or doesn't exist (which means it's still downloading) i set a placeholder image for the imageView's image, otherwise I set the downloaded image.
And after download you reload table (or just the needed cell)

Custom UITableViewCell Creates issues

Overview
I'm creating a UITableView with custom UITableViewCell (in iOS 8.4,Objective-C). i've created IBoutlets of each and every items in Custom Cell. it seems working well, but randomly my UIButton gets disappeared from custom cell.
here my CellForRowAtIndexPath Code
-(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
linkCell*cell = (linkCell*)[tableView dequeueReusableCellWithIdentifier:#"cell" forIndexPath:indexPath];
if(!cell){
cell = [[linkCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:#"cell"];
}
cell.contentView.backgroundColor = [UIColor clearColor];
NSDictionary *aDict = [numberOfSections objectAtIndex:indexPath.section];
NSDictionary* info = [[aDict objectForKey:#"Data"]objectAtIndex:indexPath.row];
static float span = 5;
static float dateviewsize = 83;
static float linesize = 1;
static float descriptionsize = 65;
//DAY_NAME
NSString* string = [self getDayNameFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayName.text = string;
//DAY_NUMBER
string = [self getDayNumberFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayNumber.text = string;
//DAY_TIME
string = [self getTimeFromDate:[info valueForKey:#"copied_url_date"]];
cell.lblDayTime.text = string;
//Link Label
if([[info objectForKey:#"copied_url_title"] isEqualToString:#"nil"]){
string = [NSString stringWithFormat:#"%#",[info valueForKey:#"copied_url"]];
cell.lblLink.font = [UIFont fontWithName:FONT_LIGHT size:14];
cell.lblLink.textColor = [UIColor colorWithRed:51.0/255.0 green:0/255.0 blue:135.0/255.0 alpha:1.0];
}else{
string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_title"]];
cell.lblLink.font = [UIFont fontWithName:FONT_MEDIUM size:16];
cell.lblLink.textColor = [UIColor darkGrayColor];
}
cell.lblLink.text = string;
float w,h,y;
w = self.view.frame.size.width-(span*2);
CGRect dataviewframe,titleRect,buttonviewrect,imageRect;
CGSize newsize;
[cell.lblDescreption setFont:[UIFont fontWithName:FONT_LIGHT size:16]];
[cell.lblDescreption setNumberOfLines:3];
[cell.linkimage setHidden:NO];
if([AFNetworkReachabilityManager sharedManager].isReachable){
//Unspacified ImageView
if([[info objectForKey:#"copied_url_img"]isEqualToString:#"nil"]){
[cell.linkimage setHidden:YES];//hide image
//make call to get image & title of Copied URL
[self MakeCallAndSetImageToImageView:indexPath ToGetImageFromURL:[info valueForKey:#"copied_url"]];
//new size of link title
y = span+dateviewsize+span+linesize+1;
if([[info objectForKey:#"copied_url_description"] isEqualToString:#"nil"]){
[cell.lblDescreption setHidden:YES];//hide description
//set dataview's new height
h = span+dateviewsize+span;
}
else{
[cell.lblDescreption setHidden:NO];//show description
NSString* string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_description"]];
[cell.lblDescreption setText:string];
newsize = [self getStringHeightWithMaxWidth:w-(span*2) AndText:cell.lblDescreption];
if(newsize.height > descriptionsize){
titleRect = CGRectMake(span,y,w-(span*2),descriptionsize);
//set dataview's new height
h = y+descriptionsize+span;
}else{
titleRect = CGRectMake(span,y,w-(span*2),newsize.height);
//set dataview's new height
h = y+newsize.height+span;
}
[cell.lblDescreption setFrame:titleRect];
}
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}else{
[cell.linkimage setHidden:NO];//show image
//new size of link image
y = span+dateviewsize+span+linesize+1;
float imageH = [self SizeWithScaledToWidth:w-(span*2)].height;
imageRect = CGRectMake(span,y,w-(span*2),imageH);
NSString* imgurl=[NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_img"]];
[cell.linkimage setImageWithURL:[NSURL URLWithString:imgurl]];
[cell.linkimage setFrame:imageRect];
y = y+imageH+span;
//new size of link title
if([[info objectForKey:#"copied_url_description"] isEqualToString:#"nil"]){
[cell.lblDescreption setHidden:YES];
h = y+span;
}else{
[cell.lblDescreption setHidden:NO];//show description
NSString* string = [NSString stringWithFormat:#"%#",[info objectForKey:#"copied_url_description"]];
[cell.lblDescreption setText:string];
newsize = [self getStringHeightWithMaxWidth:w-(span*2) AndText:cell.lblDescreption];
if(newsize.height > descriptionsize){
titleRect = CGRectMake(span,y,w-(span*2),descriptionsize);
//set dataview's new height
h = y+descriptionsize+span;
}else{
titleRect = CGRectMake(span,y,w-(span*2),newsize.height);
//set dataview's new height
h = y+newsize.height+span;
}
[cell.lblDescreption setFrame:titleRect];
}
//set dataview's new frame
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}
}else{
//NO INTERNET CONNECTION
//hide link image
[cell.linkimage setHidden:YES];
//hide link title
[cell.lblDescreption setHidden:YES];
//set dataview's new frame
h = span+dateviewsize;
dataviewframe = CGRectMake(span,span,w,h);
//set buttonview's new frame
buttonviewrect = CGRectMake(span,h+span+2,w,50);
}
cell.dataview.frame = dataviewframe;
cell.buttonview.frame = buttonviewrect;
if([selectedRow isEqual:indexPath]){
cell.buttonview.alpha=1;
}else{
cell.buttonview.alpha=0;
}
[cell.btnShare setHidden:NO];
[cell.buttonview bringSubviewToFront:cell.btnShare];
[cell.buttonview bringSubviewToFront:cell.btnOpen];
[cell.buttonview bringSubviewToFront:cell.btnCopy];
[cell.buttonview bringSubviewToFront:cell.btnDelete];
[cell.btnShare addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnOpen addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnCopy addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnDelete addTarget:self action:#selector(Action:) forControlEvents:UIControlEventTouchUpInside];
[cell.btnShare setTag:indexPath.row];
[cell.btnOpen setTag:indexPath.row];
[cell.btnCopy setTag:indexPath.row];
[cell.btnDelete setTag:indexPath.row];
return cell;
}
here is my screen shots
Thanks in Advance tell me if you want more info.
You're doing way too much in the -(UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath method. It's good practice to give a custom cell a configuration method, like -(void)configureCell, where the content and lay-out of the cell will be defined. In other words, let the cell be responsible (as much as possible) for its content and lay-out instead of the tableview.
I guess this part causes problems:
if([AFNetworkReachabilityManager sharedManager].isReachable) {
...
}
Especially:
[self MakeCallAndSetImageToImageView:indexPath ToGetImageFromURL:[info valueForKey:#"copied_url"]];
I don't know the implementation of this method, but I have the feeling you have to look over there, as it can be a threading issue at retrieving the image you requested.
One more tip: the way you name your classes and methods doesn't always follow the Objective-C conventions. Check linkCell (class) and MakeCallAndSetImageToImageView ... (method).
Possible layout broken. Try to capture view hierarchy. In Xcode: Debug > View Debugging > Capture View Hierarchy.
Also, method dequeueReusableCellWithIdentifier:forIndexPath: always returns a valid cell. if(!cell){ ... } will never be executed, you can remove it.
Try to use this block of GCD, i think it will work.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
//Do data fetching and calculation
dispatch_async(dispatch_get_main_queue(), ^(void) {
//Update UI on main thread
});
});
After a long time, i found the mistake in my code. i was setting buttonview tag indexPath.row and also gave same to button tag. and when DidSelectRowAtIndexPath get called, i was doing,
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
linkCell*cell = (linkCell*)[tableView cellForRowAtIndexPath:indexPath];
if([selectedRow isEqual:indexPath]){
selectedRow = nil;
//this is where i'm mistaking.
[[cell viewWithTag: indexPath.row]setAlpha:1];
}else{
selectedRow = indexPath;
//this is where i'm mistaking.
[[cell viewWithTag: indexPath.row]setAlpha:0];
}
[tableView reloadData];
}
so, i gave -1 tag to buttonview and the problem is solved.
if([selectedRow isEqual:indexPath]){
selectedRow = nil;
[[cell viewWithTag: -1]setAlpha:1];
}else{
selectedRow = indexPath;
[[cell viewWithTag: -1]setAlpha:0];
}
by the way thanks for your valuable Tips and Advises.

Controlling Load Ordering of UICollectionView cells with dispatch_async

In my iOS app, I have a UICollectionView where each cell contains an image. To prevent the view from taking a long time to load, I load each with a blank image and title before loading the image contents in a background task.
I logged which images are getting loaded through in the background async task, and it seems like the images of cells off screen get loaded first, followed by the cells at the top of the screen. This makes the app seem unresponsive, and I'd rather have the cells at the top take priority in terms of loading:
I also notice that once I start scrolling, the images in the cells suddenly start appearing, but they take much longer to appear on their own. Can anyone suggest strategies to control the ordering that UICollectionCells load in?
Here is my code:
Iterate over projects and add imageViews to an NSMutableArray projectContainers, which then gets turned into cells
for (NSDictionary *currentProject in projects)
{
// data entry
[projectIDs addObject: [currentProject objectForKey:#"id"]];
NSString *projectTitle = [currentProject objectForKey:#"title"];
id delegate = [[UIApplication sharedApplication] delegate];
self.managedObjectContext = [delegate managedObjectContext];
CustomLabel *cellLabel=[[CustomLabel alloc]init];
cellLabel.text = trimmedProjectTitle;
[titles addObject:projectTitle];
CGSize maxLabelSize = CGSizeMake(cellWidth,100);
CustomLabel *titleLabel = [[CustomLabel alloc]init];
// titleLabel styling
titleLabel.backgroundColor = [[UIColor blackColor]colorWithAlphaComponent:0.5f];
titleLabel.textColor =[UIColor whiteColor];
[titleLabel setFont: [UIFont fontWithName: #"HelveticaNeue" size:12]];
titleLabel.text = trimmedProjectTitle;
CGSize expectedLabelSize = [titleLabel.text sizeWithFont:titleLabel.font constrainedToSize:maxLabelSize lineBreakMode:NSLineBreakByWordWrapping];
CGRect labelFrame = (CGRectMake(0, 0, cellWidth, 0));
labelFrame.origin.x = 0;
labelFrame.origin.y = screenWidth/2 - 80 - expectedLabelSize.height;
labelFrame.size.height = expectedLabelSize.height+10;
titleLabel.frame = labelFrame;
// add placeholder image with textlabel
UIImageView *imagePreview = [[UIImageView alloc] initWithFrame:CGRectMake(0, 0, cellWidth, cellHeight)];
imagePreview.contentMode= UIViewContentModeScaleAspectFill;
imagePreview.clipsToBounds = YES;
[imagePreview setImage:[UIImage imageNamed:#"blank.png"]];
[imagePreview addSubview:titleLabel];
[imagePreview.subviews[0] setClipsToBounds:YES];
[projectContainers addObject: imagePreview];
// add project thumbnail images in async
dispatch_async(bgQueue, ^{
NSDictionary *imagePath = [currentProject objectForKey:#"image_path"];
NSString *imageUrlString = [imagePath objectForKey: #"preview"];
NSURL *imageUrl = [NSURL URLWithString: imageUrlString];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:(imageUrl)];
UIImage *image = [[UIImage alloc] initWithData:(imageData)];
if(image){
NSLog(#"project with image: %#", projectTitle);
[imagePreview setImage: image];
}
BOOL *builtVal = [[currentProject objectForKey:#"built"]boolValue];
if(builtVal){
UIImageView *builtBanner =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"built_icon.png"]];
builtBanner.frame = CGRectMake(screenWidth/2 -80, 0, 50, 50);
[imagePreview addSubview: builtBanner];
}
});
}
renders cells using the NSMutableArray projectContainers:
-(UICollectionViewCell*)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
// NSLog(#"cellForItemAtIndexPath");
static NSString *identifier = #"NewCell";
UICollectionViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if(!reloadProjects){
UIImageView *preview = (UIImageView*) [cell.contentView viewWithTag:[[projectIDs objectAtIndex:indexPath.row]intValue]];
UIImageView *previewContent = [projectContainers objectAtIndex:indexPath.row];
// NSLog(#"fetching image tag %d", [[projectIDs objectAtIndex:indexPath.row]intValue]);
if (!preview)
{
previewContent.tag = [[projectIDs objectAtIndex:indexPath.row]intValue];
// NSLog(#"creating previewContent %li", (long) previewContent.tag);
[cell addSubview: previewContent];
}
[self.collectionView setBackgroundColor:collectionGrey];
cell.contentView.layer.backgroundColor = [UIColor whiteColor].CGColor;
return cell;
}
return cell;
}
EDIT: Working Solution
Thanks to rob mayoff for helping me come out with a solution. This is what I ended up doing, which loads the images much faster:
// add project thumbnail images in async
dispatch_async(imageQueue, ^{
NSDictionary *imagePath = [currentProject objectForKey:#"image_path"];
NSString *imageUrlString = [imagePath objectForKey: #"preview"];
NSURL *imageUrl = [NSURL URLWithString: imageUrlString];
NSData *imageData = [[NSData alloc] initWithContentsOfURL:(imageUrl)];
UIImage *image = [[UIImage alloc] initWithData:(imageData)];
if(image){
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"project with image: %#", projectTitle);
[imagePreview setImage: image];
});
}
BOOL *builtVal = [[currentProject objectForKey:#"built"]boolValue];
if(builtVal){
UIImageView *builtBanner =[[UIImageView alloc]initWithImage:[UIImage imageNamed:#"built_icon.png"]];
builtBanner.frame = CGRectMake(screenWidth/2 -80, 0, 50, 50);
dispatch_async(dispatch_get_main_queue(), ^{
[imagePreview addSubview: builtBanner];
});
}
});
There are several things that code be improved in your code, but your chief complaint (“once I start scrolling, the images in the cells suddenly start appearing, but they take much longer to appear on their own”) is because you violated the commandment:
Thou shalt only access
thy view hierarchy
from the main thread.
Look at your code:
dispatch_async(bgQueue, ^{
...
[imagePreview addSubview: builtBanner];
You're manipulating the view hierarchy from a background thread. This is not allowed. For example, see the note at the bottom of this page, or the “Threading Considerations” in the UIView Class Reference.
You need to dispatch back to the main thread to update the view hierarchy.
Watch the Session 211 - Building Concurrent User Interfaces on iOS video from WWDC 2012. It talks in depth about how to do what you're trying to do, efficiently. See also this answer.

Adjusting code to include Lazy loading - scrollview and images

Im trying to refactor my code for better memory management and performance. I have an array of 12 images, but I want to load them as needed, not all at the same time. So maybe the current image -1, the current image and the current image +1. I viewed some of the answers on SO but found them unclear. I felt it would be clearer if I posted my code for reference.
//scroll view set up
- (void)scrollViewSetUp
{
self.scrollview.delegate = self;
for (int i = 0; i < _images.count; i++)
{
CGRect frame;
frame.origin.x = self.scrollview.frame.size.width * i;
frame.size = self.scrollview.frame.size;
self.scrollview.pagingEnabled = YES;
UIImageView *subview = [[UIImageView alloc] initWithFrame:frame];
subview.image = [UIImage imageNamed:[_images objectAtIndex:i]];
[self.scrollview addSubview:subview];
}
self.scrollview.contentSize = CGSizeMake(self.scrollview.frame.size.width * _images.count, self.scrollview.frame.size.height);
self.automaticallyAdjustsScrollViewInsets = NO;
//page control ie .... at bottom of
self.pageControl = [[UIPageControl alloc] initWithFrame:CGRectMake(100.0,0.0,100.0,40.0)];
[self.pageControl setNumberOfPages:_images.count];
[self.pageControl setCurrentPage:0];
self.pageControl.pageIndicatorTintColor = [UIColor lightGrayColor];
self.pageControl.currentPageIndicatorTintColor = [UIColor whiteColor];
[self.pageControl setBackgroundColor:[UIColor clearColor]];
[self.viewForPageControl addSubview:self.pageControl];
[self.viewForPageControl setBackgroundColor:[UIColor clearColor]];
}
#pragma mark - UIScrollView Delegate
- (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
int newOffset = scrollView.contentOffset.x;
int newPage = (int)(newOffset/(scrollView.frame.size.width));
[_pageControl setCurrentPage:newPage];
}
Any advice or direction is greatly appreciated.
As per Gman's request I reposted my comment.
This tutorial will help you:
http://www.raywenderlich.com/10518/how-to-use-uiscrollview-to-scroll-and-zoom-content
You could try to reuse your UIImageView as they go offscreen... but you'll be just trying to redo what UITableview already does. UITableView with a custom UITableViewCell would take care of notifying you when new cells comes visible and dequeuing the ones that are offscreen.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
NSString *cellIdentifier = #"yourCustomImageCell";
//look if there are cells that could be reused
CustomImageCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
if (!cell) { //if not, create a new one
cell = [[CustomImageCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
}
//Set your image here
return cell;
}
Not sure if this is the best way of doing it, but it's an option.
You can set the tag property on your UIImageView to correspond to your index in your loop when setting the scrollView.
Then in your scrollViewDidEndDecelerating method:
for (int i = 0; i < _salonImages.count; i++)
{
if(i == (newPage-1))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage-1];
imgView.image = [_images objectAtIndex:newPage-1];
}
else if(i == newPage)
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage];
imgView.image = [_images objectAtIndex:newPage];
}
else if(i == (newPage + 1 ))
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:newPage+1];
imgView.image = [_images objectAtIndex:newPage+1];
}
else
{
UIImageView *imgView = (UIImageView*)[self.scrollView viewWithTag:i];
imgView.image = nil;
}
}

Resources