有我的问题:
我有自定义类,它解析XML并获取我需要用作字符串URL的字符串,现在我修改了我的代码如下:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
UILabel *labelText = (UILabel *)[cell viewWithTag:1000];
labelText.text = [[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:@"name"];
dispatch_queue_t concurrentQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(concurrentQueue, ^{
NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:@"imageCell"]];
NSData *image = [[NSData alloc] initWithContentsOfURL:imageURL];
dispatch_async(dispatch_get_main_queue(), ^{
cell.imageView.image = [UIImage imageWithData:image];
});
});
return cell;
}
这非常简单,但是,我得到了不可预知的错误!在滚动表期间,图像开始混乱地变化,有时它显示3个或更多图像并且最终图像是正确的,有时最终(正确)图像根本不出现。此外,当第一次显示表格时,它实际上是空白的,所以我需要将其向下滚动,然后再向上滚动以查看我的图像!
为了解决这个问题,我添加了以下代码,以确定我的图像链接对于该indexPath是否正确:
-(void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
NSURL *imageURL = [NSURL URLWithString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row]objectForKey:@"imageCell"]];
NSLog(@"%@", imageURL);
}
当我点击任何单元格时,它确实在控制台日志中显示正确的链接,但单元格上的图像是之前显示的图像之一(无效),并且它不是该链接的图像。如何解决这些奇怪的错误?
任何建议都将不胜感激,谢谢。
答案 0 :(得分:1)
当你出列一个单元格对象时,大部分时间你都会得到一个重用的单元格,即之前一次或多次由tableView:cellForRowAtIndexPath:
配置的单元格。
要想象您的案例中发生了什么,请在执行长而快速的滚动时考虑单个单元格的一个可能的事件序列:
imageView
。这确实看起来像每个加载操作完成时图像都在混乱地变化。(更重要的是,对于并发队列,无法保证图像加载将按照它们启动的顺序完成 - 您可能无法获得正确的最终图像!)
那我们该怎么做呢?现在我们了解了这个问题,有很多不同的解决方案。一个非常简单的解决方案(我并不是真的建议)是在设置图像时检查单元格的标签文本是否与该indexPath的值匹配:
if ([labelText.text isEqualToString:[[self.listOfPlaceDetails objectAtIndex:indexPath.row] objectForKey:@"name"]]) {
cell.imageView.image = [UIImage imageWithData:image];
}
显然,这假设所有地方细节都有唯一的名称。
更好的解决方案可能是创建一个处理图像下载的对象,并且可以注册/取消注册单元格以处理下载完成。此对象可以强制执行单元格无法等待多个图像加载的条件。正如@Leena指出的那样,缓存是一个好主意,这个对象也可能对此负责。
对于空白图像,在设置图像后调用[cell setNeedsLayout]
应该将其排序。
答案 1 :(得分:1)
默认属性" imageView"不会被添加到单元格,直到它的(imageView' s)属性"图像"是零(你可以检查cell.imageView.superview也将是零)。 这就是为什么你的tableView在加载时是空白的,并且还加载了单元格的所有图像。 所以当你向下滚动(或向上)时,将重新加载单元格,它们的" imageView"将有图像数据。这就是他们在单元格上的原因,你可以看到它们。
另一个问题是您的图像一直在闪烁。这是因为你的细胞出列了。 因此,当下载并设置第一个单元格的图像时,它将不会显示,直到您重新出现单元格的子视图(例如通过调用[cell setNeedsLayout] ;-)。 当您向下滚动表格时,您的第一个单元格(现在带有图像)将从" tableView"并将成为最后一个单元格,然后您的第一个单元格将显示实际属于第一行的图像。 同时你开始下载这个(最后一行)的图像,下载后你将设置它。闪光发生时,这就是一个因素。