在单元格中异步加载图像的 UITableView - 图像在慢速连接时不断变化
UITableView with asynchronous loading of image in cells - images keep changing on slow connection
我正在 table 视图中异步加载图像。在连接速度较慢时,单元格中的图像保持 flickering/changing(我假设它来自重复使用单元格)。我听从了其他一些相关问题的建议,包括:
- 缓存图像
- 设置占位符图片
在正常连接上没有问题,但是在EDGE和慢速网络上,问题仍然存在。我想知道是否正在使用网络请求备份全局队列?如果是这样,我该如何解决?
这是我的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get the data for this photo post
NSDictionary *data = [self.streamPhotosData objectAtIndex:indexPath.row];
static NSString *CellIdentifier = @"StreamPhotoTableViewCell";
__block StreamPhotoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StreamPhotoTableViewCell"];
if (cell == nil) {
cell = [[StreamPhotoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.delegate = self;
// check if image in cache, else cache it
if ([[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]] != nil) {
// cache hit
cell.photoImageView.image = [[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]];
} else {
// set a placeholder image
cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];
// download the image asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];
if (downloadedImage) {
dispatch_async(dispatch_get_main_queue(), ^{
cell.photoImageView.image = downloadedImage;
// update cache
[[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
});
}
});
}
return cell;
}
我曾经遇到过类似的问题。
为什么会这样?
假设您在第 1 行的 cellForRow 中,此图像不在缓存中,因此您正在下载它。同时,您滚动 tableView,假设现在您在 cellForRow 中的第 8 行,这是同一个单元格实例。
假设现在缓存中有此图像,所以您只需设置没有时间偏移的图像,并且在单元格包含正确的图像后,第 1 行的图像已准备就绪,请记住它是相同的单元格实例,因此图像将被替换。
当然这只是一个例子。
你可以试试'remember'你从哪一行开始下载图片,在开始下载之前设置一个'beforeTag',然后是,检查如果相同indexPath.row
NSInteger beforeTag = indexPath.row;
// download the image asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];
if (downloadedImage) {
dispatch_async(dispatch_get_main_queue(), ^{
if (indexPath.row == beforeTag) {
cell.photoImageView.image = downloadedImage;
}
// update cache
[[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
});
}
});
此外,我会将这一行放在您自定义单元格的 prepareForReuse 中:
cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];
每次重用 UITableViewCell 时都会调用此方法,它会在您“dequeueReusableCellWithIdentifier”之后调用,如果单元格已经存在。并且总是放一个占位符图像是可以的,如果图像在缓存中,你不会注意到这个占位符。
希望对您有所帮助
我正在 table 视图中异步加载图像。在连接速度较慢时,单元格中的图像保持 flickering/changing(我假设它来自重复使用单元格)。我听从了其他一些相关问题的建议,包括:
- 缓存图像
- 设置占位符图片
在正常连接上没有问题,但是在EDGE和慢速网络上,问题仍然存在。我想知道是否正在使用网络请求备份全局队列?如果是这样,我该如何解决?
这是我的代码:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
// get the data for this photo post
NSDictionary *data = [self.streamPhotosData objectAtIndex:indexPath.row];
static NSString *CellIdentifier = @"StreamPhotoTableViewCell";
__block StreamPhotoTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"StreamPhotoTableViewCell"];
if (cell == nil) {
cell = [[StreamPhotoTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
cell.delegate = self;
// check if image in cache, else cache it
if ([[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]] != nil) {
// cache hit
cell.photoImageView.image = [[[GlobalCaches getCurrentInstance] photoCache] objectForKey:[data objectForKey:@"photoGuid"]];
} else {
// set a placeholder image
cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];
// download the image asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];
if (downloadedImage) {
dispatch_async(dispatch_get_main_queue(), ^{
cell.photoImageView.image = downloadedImage;
// update cache
[[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
});
}
});
}
return cell;
}
我曾经遇到过类似的问题。
为什么会这样? 假设您在第 1 行的 cellForRow 中,此图像不在缓存中,因此您正在下载它。同时,您滚动 tableView,假设现在您在 cellForRow 中的第 8 行,这是同一个单元格实例。 假设现在缓存中有此图像,所以您只需设置没有时间偏移的图像,并且在单元格包含正确的图像后,第 1 行的图像已准备就绪,请记住它是相同的单元格实例,因此图像将被替换。 当然这只是一个例子。
你可以试试'remember'你从哪一行开始下载图片,在开始下载之前设置一个'beforeTag',然后是,检查如果相同indexPath.row
NSInteger beforeTag = indexPath.row;
// download the image asynchronously
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) {
UIImage *downloadedImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:[data objectForKey:@"url"]]]];
if (downloadedImage) {
dispatch_async(dispatch_get_main_queue(), ^{
if (indexPath.row == beforeTag) {
cell.photoImageView.image = downloadedImage;
}
// update cache
[[[GlobalCaches getCurrentInstance] photoCache] setObject:downloadedImage forKey:[data objectForKey:@"photoGuid"]];
});
}
});
此外,我会将这一行放在您自定义单元格的 prepareForReuse 中:
cell.photoImageView.image = [UIImage imageNamed:@"placeholder.png"];
每次重用 UITableViewCell 时都会调用此方法,它会在您“dequeueReusableCellWithIdentifier”之后调用,如果单元格已经存在。并且总是放一个占位符图像是可以的,如果图像在缓存中,你不会注意到这个占位符。
希望对您有所帮助