Iphone 表视图会混淆图像
我使用在TableView中加载和显示异步图像。但有时当我快速上下滚动时,它会混合所有图像并显示在其他行中。这是我的cellForRowAtIndexPath:Iphone 表视图会混淆图像,iphone,ios,uitableview,sdwebimage,Iphone,Ios,Uitableview,Sdwebimage,我使用在TableView中加载和显示异步图像。但有时当我快速上下滚动时,它会混合所有图像并显示在其他行中。这是我的cellForRowAtIndexPath: - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"Cell"; CustomTable
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
CustomTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
// Configure the cell.
MWFeedItem *item = [itemsToDisplay objectAtIndex:indexPath.row];
if (item) {
// Parse out Image URL for cell
if (cell.imageView.image == nil) {
NSError *error = NULL;
NSRegularExpression *regexImage = [NSRegularExpression regularExpressionWithPattern:@"(<img\\s[\\s\\S]*?src\\s*?=\\s*?['\"](.*?)['\"][\\s\\S]*?>)+?"
options:NSRegularExpressionCaseInsensitive
error:&error];
[regexImage enumerateMatchesInString:item.content
options:0
range:NSMakeRange(0, [item.content length])
usingBlock:^(NSTextCheckingResult *result, NSMatchingFlags flags, BOOL *stop) {
NSString *src = [item.content substringWithRange:[result rangeAtIndex:2]];
NSLog(@"img src: %@", src);
[cell.imageView setImageWithURL:[NSURL URLWithString:src]];
}];}
if (cell.imageView.image == nil) {
cell.imageView.image = [UIImage imageNamed:@"video.png"];
}
return cell;
}
我不知道怎么了,但我想这是因为我在单元格中解析图像,但速度不够快,所以它会一次又一次地启动。你能告诉我如何解决这个问题吗?我相信,高层次的答案是,当你滚动时,你是在完成将图像放入单元格之前重复使用单元格。不管怎样,当我在代码中看到这一点时,这就是它的含义 我不使用SDWebImage,也不知道setImageWithURL变体是什么,但github网页有一个“如何使用”的说明,可以在图像获取成功或失败时给它一个完成块来执行。 因此,当您最终获得图像时,但在将其放入UITableViewCell之前,您需要检查该单元格是否仍被分配给与开始获取图像时相同的indexPath。由于setImageWithURL似乎总是设置图像,因此您必须将临时UIImageView放置在单元格中,而不是直接放置在单元格中。我查看的文档有一个方法调用,其中包含placeholder image:和completed:两个选项,使用它们可以执行类似于未检查编译器的代码:
// before you go off to get the image, save the indexPath of the cell
NSIndexPath *originalIndexPath = indexPath;
UIImageView *tempImageView;
[tempImageView setImageWithURL:[NSURL URLWithString : [NSURL URLWithString:src]]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
// completion block
// You probably want to check that it really succeeded, but if it did
// Now you have an image in the image parameter and probably in tempImageView.
// Check to see if the cell is still at the original indexPath
// If so, put the image in.
// If not, the row was scrolled out of sight and the cell has been reused
// so just drop the image on the floor -- it is no longer useful
NSIndexPath *currentIndexPath = [self.tableview indexPathForCell:cell]
if ([currentIndexPath isEqual originalIndexPath]) {
cell.imageView.image = image;
// or perhaps: cell.imageView.image = tempImageView.image;
}
}];
高层次的答案是,我相信,当你滚动时,你是在把图像放入细胞之前重用细胞。不管怎样,当我在代码中看到这一点时,这就是它的含义 我不使用SDWebImage,也不知道setImageWithURL变体是什么,但github网页有一个“如何使用”的说明,可以在图像获取成功或失败时给它一个完成块来执行。 因此,当您最终获得图像时,但在将其放入UITableViewCell之前,您需要检查该单元格是否仍被分配给与开始获取图像时相同的indexPath。由于setImageWithURL似乎总是设置图像,因此您必须将临时UIImageView放置在单元格中,而不是直接放置在单元格中。我查看的文档有一个方法调用,其中包含placeholder image:和completed:两个选项,使用它们可以执行类似于未检查编译器的代码:
// before you go off to get the image, save the indexPath of the cell
NSIndexPath *originalIndexPath = indexPath;
UIImageView *tempImageView;
[tempImageView setImageWithURL:[NSURL URLWithString : [NSURL URLWithString:src]]
placeholderImage:[UIImage imageNamed:@"placeholder.png"]
completed:^(UIImage *image, NSError *error, SDImageCacheType cacheType) {
// completion block
// You probably want to check that it really succeeded, but if it did
// Now you have an image in the image parameter and probably in tempImageView.
// Check to see if the cell is still at the original indexPath
// If so, put the image in.
// If not, the row was scrolled out of sight and the cell has been reused
// so just drop the image on the floor -- it is no longer useful
NSIndexPath *currentIndexPath = [self.tableview indexPathForCell:cell]
if ([currentIndexPath isEqual originalIndexPath]) {
cell.imageView.image = image;
// or perhaps: cell.imageView.image = tempImageView.image;
}
}];
将单元格标识符从更改为
static NSString *CellIdentifier = @"Cell";
到
将单元格标识符从更改为
static NSString *CellIdentifier = @"Cell";
到
setImageWithURL是由SDWebImage指定的方法。你能告诉我上面的代码放在哪里吗?好的,我简单地看了SDWebImage并编辑了我的答案。您需要自己将图像放入单元格中,但前提是单元格未被重用。关于如何将其用于tableview的简单示例是错误的,因为它正是您遇到的问题。每当您使用TableView进行异步图像处理时,您都需要进行此类检查,以确保单元格仍然具有相同的标识,即滚动不会导致单元格被取消分配,然后可能被重新使用。感谢您为此所做的努力。如果[currentIndexPath isEqual originalIndexPath]中说必须有一个:before,我会在该行中得到一个错误originalIndexPath@Supporter_04尝试按照错误提示插入冒号:[currentIndexPath isEqual:originAlinIndexPath]对不起,我有点傻:P。如你所见,我使用了上面的答案,因为它只有一行@CharliePrice非常感谢您的努力SetImageWithURL是SDWebImage指定的一种方法。你能告诉我上面的代码放在哪里吗?好的,我简单地看了SDWebImage并编辑了我的答案。您需要自己将图像放入单元格中,但前提是单元格未被重用。关于如何将其用于tableview的简单示例是错误的,因为它正是您遇到的问题。每当您使用TableView进行异步图像处理时,您都需要进行此类检查,以确保单元格仍然具有相同的标识,即滚动不会导致单元格被取消分配,然后可能被重新使用。感谢您为此所做的努力。如果[currentIndexPath isEqual originalIndexPath]中说必须有一个:before,我会在该行中得到一个错误originalIndexPath@Supporter_04尝试按照错误提示插入冒号:[currentIndexPath isEqual:originAlinIndexPath]对不起,我有点傻:P。如你所见,我使用了上面的答案,因为它只有一行@查理·普莱斯非常感谢您的邀请effort@Supporter_04,这可能会起作用,但在我看来,它似乎为每个数据项创建了一个新的单元格,因此您不会得到任何单元格重用。这会降低UITableView的内存效率。Charlie的答案可能更难实现您需要正确理解SDWebImage的细节,但它尊重单元重用的原则。当然,这不是性能的最佳解决方案,但我认为他需要快速解决方案:@Supporter_04,这可能行得通,但在我看来,它似乎为每个数据项创建了一个新单元,所以你没有得到任何细胞重复使用。这会降低UITableView的内存效率。查理的答案可能更难实现,你会的
需要正确理解SDWebImage的细节,但它尊重单元重用原则。当然,这不是性能的最佳解决方案,但我认为他需要快速解决方案: