3 回答
TA贡献1827条经验 获得超4个赞
这里的问题是您的图像获取块正在保存对tableview单元的引用。下载完成后,imageView.image即使您回收了单元格以显示其他行,它也会设置属性。
在设置映像之前,您需要下载完成块来测试映像是否仍与单元格相关。
还需要注意的是,您不会将图像存储在单元格中以外的任何位置,因此,每次在屏幕上滚动一行时,您都将再次下载它们。您可能希望将它们缓存在某个位置,并在开始下载之前查找本地缓存的图像。
编辑:这是使用单元格的tag属性进行测试的简单方法:
- (UITableViewCell *)tableView:(UITableView *)tableView
cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
cell.tag = indexPath.row;
NSDictionary *parsedData = self.loader.parsedData[indexPath.row];
if (parsedData)
{
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:parsedData[@"imageLR"]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
if (image) {
dispatch_async(dispatch_get_main_queue(), ^{
if (cell.tag == indexPath.row) {
cell.imageView.image = image;
[cell setNeedsLayout];
}
});
}
});
cell.textLabel.text = parsedData[@"id"];
}
return cell;
}
TA贡献1993条经验 获得超5个赞
关键是您没有完全了解单元重用概念。这与异步下载不太吻合。
块
^{
cell.imageView.image = image;
[cell setNeedsLayout];
}
在请求完成并且所有数据都已加载时被执行。但是,在创建块时,单元会获得其值。
到执行块时,单元仍指向现有单元之一。但是用户很有可能继续滚动。同时,该单元格对象已被重新使用,并且该图像与“ 旧 ”单元格相关联,该单元格已被重用,分配和显示。之后不久,除非用户进一步滚动,否则将加载并分配并显示正确的图像。等等等等。
您应该寻找一种更聪明的方法。有很多花絮。Google用于延迟加载图片。
TA贡献1719条经验 获得超6个赞
使用索引路径获取单元格。如果看不到该单元格nil,则不会有问题。当然,您可能希望在下载数据时缓存数据,以便在已有图像后立即设置单元格的图像。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (self.loader.parsedData[indexPath.row] != nil)
{
cell.imageView.image = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);
dispatch_async(queue, ^(void) {
// You may want to cache this explicitly instead of reloading every time.
NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self.loader.parsedData[indexPath.row] objectForKey:@"imageLR"]]];
UIImage* image = [[UIImage alloc] initWithData:imageData];
dispatch_async(dispatch_get_main_queue(), ^{
// Capture the indexPath variable, not the cell variable, and use that
UITableViewCell *blockCell = [tableView cellForRowAtIndexPath:indexPath];
blockCell.imageView.image = image;
[blockCell setNeedsLayout];
});
});
cell.textLabel.text = [self.loader.parsedData[indexPath.row] objectForKey:@"id"];
}
return cell;
}
- 3 回答
- 0 关注
- 522 浏览
添加回答
举报