0

每次我滚动 TableView 时,我的图像都会乱七八糟,主要是第一行。我真的不知道该怎么办。

这是代码:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *cellIdentifier = @"Cell";

    BarCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

    [cell.activityFotoBar startAnimating];
    cell.activityFotoBar.hidesWhenStopped = YES;

   if(!cell){
       cell = [[BarCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
   }

    NSMutableDictionary *infoBar = [self.bares objectAtIndex:indexPath.row];
    NSString *nomeImagem = [infoBar objectForKey:@"foto"];

    NSURL *url = [NSURL URLWithString:nomeImagem];
    NSURLRequest *requestImagem = [NSURLRequest requestWithURL:url];
    [NSURLConnection sendAsynchronousRequest:requestImagem queue:[NSOperationQueue currentQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {

        if(connectionError == nil){
            cell.imageViewImagemBar.image = [UIImage imageWithData:data];
            [cell.activityFotoBar stopAnimating];
        }

    }];


    cell.labelNomeBar.text = [infoBar objectForKey:@"nome"];
    cell.labelEnderecoBar.text = [infoBar objectForKey:@"endereco"];
    cell.labelAvaliacaoBar.text = [NSString stringWithFormat:@"Votos: %@", [infoBar objectForKey:@"votos"]];

    return cell;

}

提前致谢!

4

3 回答 3

1

出现问题是因为异步图像请求在您的单元格滚动出屏幕并被重用后完成。下载完全“乱序”,导致视觉混乱。从本质上讲,一些通过滚动重新使用的单元仍然是“热的”,因为它们的图像加载正在进行中。重用此类单元格会在新旧图像下载之间产生竞争。

您应该更改用于加载图像的策略:与其发送请求并“忘记”它,不如考虑使用connectionWithRequest:delegate:方法,将连接存储在单元格中,并在调用方法cancel时调用它prepareForReuse。这样,您重复使用的单元格将是“冷的”。

于 2013-09-23T16:29:18.097 回答
0

您可以使用 SDWebcache 库。它包含一个 UIImageView 类别类,可以从 url 加载图像。我发现它适用于 tableviews

于 2013-09-23T16:40:00.017 回答
0

代码应该“几乎”工作。您只需要解决一个问题即可使其正常工作(尽管不是最佳状态):

当异步请求sendAsynchronousRequest:queue:completionHandler:完成时,将调用完成处理程序。然后,您需要在请求开始时从指定indexPath的表视图中再次检索单元格。

您只需要捕获块内的indexPath以获得在块完成之前保持有效的引用。

UITableView方法来检索单元格是

- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath

如果返回值(一个单元格)是nil索引路径处的单元格indexPath是不可见的。

因此,完成块将如下所示:

    if (error == nil && ... ) {
        BarCell* cell = [self.tableView cellForRowAtIndexPath:indexPath]
        if (cell) {
            cell.imageViewImagemBar.image = [UIImage imageWithData:data];
            [cell.activityFotoBar stopAnimating];
        }
    }

这也可以安全地处理单元格为零的情况。

注意:虽然这“有效”,但它仍然是一种幼稚的方法。一种更复杂的方法将缓存(解码的)图像,并且可能有一些“前瞻性和急切的驱逐策略”,以获得更好的用户体验和更低的内存占用。

请注意,这imageWithData:可能仍然很昂贵,因为它可能需要在渲染之前对图像进行解码、解压缩和调整大小。基本上,这可以在屏幕外上下文中预先执行。

于 2013-09-23T17:37:40.310 回答