Helo all,
我在这里遇到一个非常奇怪的情况。我有一个表视图,其中我有自定义单元格。所以我设计了自己的自定义单元格。在自定义单元格中我也显示图像以及文本。表格的数据来自服务器。如果json中有任何图像,则显示图像,否则只显示文本。因此单元格将是动态的。我已经使用bezier path
来围绕图像包装文本。如果图像在那里,那么文本将被包装。当我从服务器添加带有图像和放大器的新帖子时我刷新表然后它自动显示其他帖子的图像。它将显示相同的图像,最后是相同的图像。我不知道为什么新单元格在其单元格中添加图像即使代码工作正常我有使用断点对其进行dbug。请告诉可能是什么问题。
以下是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;
}
答案 0 :(得分:1)
请记住,细胞会被重复使用。如果您在表数据源中有10000行,则表视图不会创建那么多行。它只会在屏幕上显示足够的行以及其他一些要预加载的行
每次滚动表格时,tableview将使用那些不可见的单元格来加载刚刚变为可见的新单元格,从而产生无限量行的错觉。这就是为什么那些新细胞拥有旧数据的原因。所以基本上,如果没有可用的图像,您必须在UIImageView
中将nil
的图像设置为cellForRowAtIndexpath:
。
if([user_post.post_image isEqualToString:@"none"] && [user_post.post_video isEqualToString:@"none"])
{
NSLog(@"NOT INSIDE THE CONDITION");
}
在上面的代码中,您只需打印一份日志,而您还需要做的是将UIImageView's
图片设置为nil
。
所以这是我的建议:
//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];
}
也许这段代码不符合您对数据显示方式的要求,但希望它可以帮助您实现这个想法!
答案 1 :(得分:0)
当需要显示tableview单元格时,您将创建一个新单元格或重新使用之前创建但在屏幕上不再可见的单元格单元格。由于您已创建UIImageView
并将其添加到单元格,因此在重复使用时,图像仍然存在。
要阻止这种情况发生,您需要保留对imageview的引用,以便下次您可以将其删除。由于您是动态添加它们并且没有IBOutlet
您最快的选择是为图像分配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
通过标记图像,下次您可以访问它:
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)
}
请务必相应地重构代码,这样如果您从标记中找到图像,则无需重新创建它等等
答案 2 :(得分:0)
您的img_profile
正在重复,因为您正在重新使用该单元格。
替换以下代码行
[cell.img_profile setImageWithURL:[NSURL URLWithString:[IMAGE_BASE_URL stringByAppendingString:user_post.user_profileImage]]placeholderImage:[UIImage imageNamed:@"post_placeholder.png"]];
以下代码: -
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"]];
}
说明: - 检查您的json是否包含用户配置文件图像然后设置图像,否则隐藏配置文件图像视图。
答案 3 :(得分:0)
表格视图重复使用单元格。这意味着,如果您将单个子视图添加到单元格,就像在[cell.tv_post addSubview:tv_image]
行上一样,那么该子视图在重复使用时仍将位于单元格中。
基本上,如果要将子视图添加到tableView:cellForRowAtIndexPath:
中的自定义单元格,则可能会犯错误。
首先将tv_image
视图设计到HomeCell
。 HomeView
应该有一个名为tv_image
的插座,连接到故事板或XIB中的图像视图。当您需要tv_image
时,请显示它。否则,隐藏它。
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;
}
此外,请确保setImageWithURL:placeholderImage:
在加载图片时未设置图片视图的hidden = NO
。
答案 4 :(得分:0)
我想知道你在哪里分配自定义单元格。如果没有创建单元格,则不应该创建单元格。像这样:
static NSString *CellIdentifier = @"homeCell";
HomeCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if(!cell)
{
cell = [[[HomeCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]];
}
然后更新UI组件。
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];
}
也许你应该在“HomeCell”课程中写一个“更新方法”。更新UI组件。
答案 5 :(得分:0)
我建议使用[SDWebImage] [1] https://github.com/rs/SDWebImage,如果需要,您可以在完成块或缓存图像中更新单元格
答案 6 :(得分:0)
问题有两个方面:
[cell.img_profile setImageWithURL:...];
异步,这意味着在下载图片时,您的单元格可能会被重复使用,因此在重复使用时清除imageView 不帮忙。要在可重复使用的单元格中正确使用图像的异步加载,您必须在加载成功时仔细检查它是否是正确的图像。
向单元格类添加属性:
@property (weak) NSURL *targetImageUrl;
然后更改加载以添加支票:
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) {
}];
答案 7 :(得分:0)
由于每当单元格变得可见时都会调用cellForRowAtIndexPath,我总是使用下一个策略来显示需要从Web加载的图像:我将图像(下载时)和objc_setAssociatedObject与包含数据的对象相关联表格行,或创建一些hashMap,其中我把图像与密钥的一些id。然后在cellForRowAtIndexPath中检查关联对象是否为nil(或者如果关键字的图像存在于hashmap中)。如果它是零或不存在(这意味着它仍在下载)我为imageView的图像设置占位符图像,否则我设置下载的图像。 下载后你重新加载表(或只是需要的单元格)