单元格背景图像已下载,但在完成下载后需要 5 秒才能出现

Posted

技术标签:

【中文标题】单元格背景图像已下载,但在完成下载后需要 5 秒才能出现【英文标题】:cell Background images are downloaded but take 5 seconds to appear right after finishing download 【发布时间】:2014-06-14 22:28:43 【问题描述】:

我希望 UITableView 在被点击后立即出现。在 UITableView 的每个单元格中都有一个从 Flickr 获取的背景图像,因此必须在后台线程中下载图像。

所以一切正常,图像在单独的线程中成功下载。但问题是,您必须在下载完成后等待 5 秒,图片才能真正出现在每个单元格中:

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

    static NSString *CellIdentifier = @"rightMenuCell";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];

    UILabel *lblTitle = (UILabel *)[cell viewWithTag:1];
    UIImageView *imgCube = (UIImageView *)[cell viewWithTag:2];
    UIActivityIndicatorView *spinnerFlickr = (UIActivityIndicatorView *)[cell viewWithTag:4];

    // Configure the cell...
    NSDictionary *region = self.regions[indexPath.row];

    //default hashtag is life
    NSString *hashTag;

    cell.detailTextLabel.text = [region valueForKeyPath:@"name"];
    cell.detailTextLabel.hidden = TRUE;
    lblTitle.text = [region valueForKeyPath:@"name"];

    NSString *regionType = [region valueForKeyPath:@"region"];
    if ([regionType  isEqual: @"neighborhood"]) 
        hashTag = @"houses";
        cell.textLabel.text = @"neighborhood";
     else if ([regionType  isEqual: @"locality"]) 
        hashTag = @"urban";
        cell.textLabel.text = @"locality";
     else 
        hashTag = @"life";
        cell.textLabel.text = @"administrative_area_level_2";
    

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0),
                   ^
                       UIImageView *imgBackground = (UIImageView *)[cell viewWithTag:3];
                       [imgBackground setClipsToBounds:YES];

                       NSLog(@"loading image data...");
                       NSString *flickrURL = [NSString stringWithFormat:@"http://domfa.de/get_image/?text=%@&lat=%f&long=%f", hashTag, self.latitude, self.longitude];
                       NSData *image = [[NSData alloc] initWithContentsOfURL: [NSURL URLWithString: flickrURL]];

                       UIImage *cellBG = [[UIImage alloc] init];
                       cellBG = [UIImage imageWithData:image];
                       imgBackground.image = cellBG;
                       [imgBackground reloadInputViews];

                       NSLog(@"images loaded!");

                       imgBackground.image = cellBG;
                       [spinnerFlickr stopAnimating];
                   );

    return cell;

基本上每个单元格都会异步下载背景图像,但即使在下载完成后,我也必须点击一个单元格或等待 5 秒,然后 2/3 的单元格将加载图像。

【问题讨论】:

确保你的表格视图在主线程上。 【参考方案1】:

dispatch_get_global_queue() 获取后台队列,而不是主队列。你只能在主队列中做与 UI 相关的事情。您的图像提取应该如下所示:

dispatch_async(dispatch_get_global_queue(…) , 
^

    // Do non-UI-related things like fetch your UIImage from the network
    UIImage *image = [self fetchAndCacheImageAtURL:imageURL] ;

    dispatch_async(dispatch_get_main_queue() , 
    ^
        // Assign your UIImage to your UIImageView
        UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath] ;
        if( cell )
             cell.imageView.image = image ;
    ) ;
) ;

请注意,在第二个dispatch_async() 中,我再次使用-cellForRowAtIndexPath: 获取单元格。这是因为在这段代码运行时,原始单元格可能已被重新用于 不同 索引路径(因为,例如,用户一直在滚动)。实际上,当前索引路径可能没有单元格,因为该索引路径可能已滚动到屏幕外。这一点,加上检查单元格是否为零,确保您将图像设置在该索引路径的正确单元格上。

【讨论】:

另外,一旦你回到主队列,你需要考虑cell由于滚动而被重复使用的可能性。 @AaronBrager,leftspin 的代码确实允许这样做。他正在使用 tableView 方法 cellForRowAtIndexPath,它将获取指定 indexPath 的 CURRENT 单元格,即使它是不同的单元格,或者不再在屏幕上。

以上是关于单元格背景图像已下载,但在完成下载后需要 5 秒才能出现的主要内容,如果未能解决你的问题,请参考以下文章

下载内部图像后调整 UICollectionView 单元格的大小

图像下载后调整表格单元格大小

图像在表格视图单元格中下载后调整大小

异步图像下载和调整图像高度后如何更新表格视图单元格

如何在图像下载和高度约束迅速改变后更新表格视图单元格高度?

下载图片后重新加载 CollectionView 的单元格