我的目标是设置文本,然后对图像进行异步调用,并在到达时设置图像 .
我目前在 UITableViewCell
中设置异步调用图像,并注意到我之前的技术导致我最近发现了一个循环:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [_tableView dequeueReusableCellWithIdentifier:@"id"];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"id"];
}
[NSURLConnection sendAsynchronousRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:userAvatar]] queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
if (data) {
UIImage* avatarImage = [UIImage imageWithData:data];
if (avatarImage) {
dispatch_async(dispatch_get_main_queue(), ^{
[cell.imageView setImage:avatarImage];
});
/*
.--. [STOP]
.----' '--. |
'-()-----()-' |
If I include the following,
the program goes in a loop,
and have not readily identified workaround:
dispatch_async(dispatch_get_main_queue(), ^{
[_tableView reloadData];
});
[GO] .--.
| .----' '--.
| '-()-----()-'
*/
}
}
}];
cell.textLabel.text = @"foo";
cell.detailTextLabel.text = @"bar";
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
return cell;
}
有没有一种方法可以产生我想要的结果而没有自定义类中的自定义setter?
1 回答
你绝对不希望每次加载图像时都调用-reloadData,它太重了,并且还会导致重新加载所有单元格,就像你发现的那样调用这个方法 .
我不清楚你为什么要调用-reloadData,因为这应该已经工作,因为设置图像的imageView上的图像将导致显示刷新...除了:
此代码中存在一个很大的逻辑错误,因为单元格一直在重复使用,但是您异步加载图像然后将其设置为特定单元格 . 在图像加载时,无法保证单元格仍将分配到表格的同一行 - 您只需在该点的随机单元格上设置图像 .
通常,tableViews只能创建足够的单元格,因为它们可以在屏幕上同时显示,而不是每行一个 . 当您向下滚动表格时,顶部的单元格将被移除并在下方重新使用,以节省内存和创建时间 .
不是直接在单元格上设置图像,而是在tableView中按行(如果它仍然可见)再次查找单元格,并将其设置为该方式 .
此外,您没有缓存您获取的图像,这将导致每次用户向下滚动然后再向上滚动时进行新的提取 . 虽然内置网络代码会进行某种程度的缓存,但您永远不知道它有多少,并且将HTTP请求更改为完整映像肯定不会很快,因此您希望自己缓存这些映像,与原始URL或行或任何键唯一地标识它们 .