UITableView On Screen Image下载延迟加载

时间:2013-03-08 09:44:21

标签: ios objective-c xcode uitableview uiscrollview

首先,这不是重复。我看到了一些相同的问题,但由于我的问题有所不同,他们没有帮助我。

使用以下代码,我将在项目中异步下载图像。

{
    NSURL *imageURL = [NSURL URLWithString:imageURLString];
    [self downloadThumbnails:imageURL];
}

- (void) downloadThumbnails:(NSURL *)finalUrl
{
    dispatch_group_async(((RSSChannel *)self.parentParserDelegate).imageDownloadGroup, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{

        NSData *tempData = [NSData dataWithContentsOfURL:finalUrl];

        dispatch_async(dispatch_get_main_queue(), ^{

            thumbnail = [UIImage imageWithData:tempData];
        });
    });
}

由于程序的逻辑,我在tableview控制器以外的文件中使用了上述代码,该控制器在从Web服务获取数据后显示所有数据。

问题:在我滚动之前,屏幕图像不会显示。屏幕外图像首先刷新。我该怎么做才能解决我的问题。

Apple的延迟加载项目使用scrollViewDidEndDragging和scrollViewDidEndDecelerating来加载图像,但项目太大而无法理解,而且我的代码在tableview控制器以外的文件中。

注意:请不要推荐像SDWebImage等第三方库。

更新:由于大多数人都无法解决问题,我必须澄清此问题与下载,缓存和重新加载tableview中的图像无关。所以请不要推荐第三方库。问题是图像仅在用户滚动tableview时显示,而不是加载屏幕上的图像。

提前致谢

4 个答案:

答案 0 :(得分:4)

我认为你要做的是:

  1. 在下载图像时在表格单元格中显示一些占位符图像(否则您的表格看起来是空的);

  2. 当下载的图像存在时,向您的表发送刷新消息。

  3. 对于2,您有两种方法:

    1. 简单一个:将reloadData发送到您的表格视图(并检查您应用的效果);

    2. 向您的表格视图发送消息:

      - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
      
    3. 使用reloadRowsAtIndexPaths要好得多,但需要您跟踪哪个图片与哪个表格行相关联。

      请注意,如果您使用Core Data存储图片,那么通过将NSFetchedResultController与您的表格视图相结合,可以更轻松地完成此工作流程。 See here for an example

      另一种方法是使用KVO:

      1. 在ItemsViewCell中声明这个观察方法:

        - (void)observeValueForKeyPath:(NSString *)keyPath
                      ofObject:(id)object
                        change:(NSDictionary *)change
                       context:(void *)context {
        
        if ([keyPath isEqual:@"thumbnail"]) {
          UIImage* newImage = [change objectForKey:NSKeyValueChangeNewKey];
          if (newImage != (id)[NSNull null]) {
            self.thumbContainer.image = newImage;
            [self.thumbContainer setNeedsLayout];
          }
        }
        
        }
        
      2. 然后,当你配置单元格时:

        RSSItem *item = [[channel items] objectAtIndex:[indexPath row]];
        cell.titleLabel.text = [item title];
        cell.thumbContainer.image = [item thumbnail];
        
        [item addObserver:cell forKeyPath:@"thumbnail" options:NSKeyValueObservingOptionNew context:NULL];
        
      3. 通过这样做,只要给定的cell“缩略图”密钥路径发生变化,就会通知item

        另一个必要的变化是做这样的任务:

               self.thumbnail = [UIImage imageWithData:tempData];
        

        (即使用self.)。

        另一个编辑:

          

        我想下载并加载图像,就像Apple的LazyTableImages示例一样。当它没有减速和拖动时,只加载屏幕上的图像,而不是一次加载所有图像。

        我怀疑我们在这里谈论不同的问题。

        我认为你的问题是下载的图像没有正确显示(如果你不滚动表格)。这是我从你的问题中理解的,我的建议解决了这个问题。

        对于延迟加载,你正在做什么(下载整个feed然后整个归档)和你想要的(懒加载)之间存在某种不匹配。这两件事并不匹配,所以你应该重新考虑你在做什么。

        除此之外,如果您想延迟加载图片,可以按照以下步骤操作:

        1. 请勿在{{1​​}}中加载图片,只需存储图片网址;

        2. 开始在parser:foundCDATA:下载图片(如果您知道该网址,则可以在单独的帖子中使用dataWithContentOfURL);

        3. 我上面发布的代码会在图片出现时更新表格;

        4. 首先,不要担心滚动/拖动,只需1-2-3工作;

        5. 一旦工作,在滚动/拖动过程中使用滚动/拖动代理阻止图像下载(第2点);您可以在表格视图中添加一个标记,只有当标记显示“没有滚动/拖动”时才会tableView:cellForRowAtIndexPath:下载图像。

        6. 我希望这足以让你达到最终结果。我不会为此编写代码,因为它非常简单。

          PS:如果您懒得加载图片,您的Feed将存储在没有图像的磁盘上;你也可以删除CGD组和CGD等待。正如我所说,没有办法解决这个问题:你不能进行延迟加载,同时使用Feed归档图像(除非每次你得到一个新的图像,你归档整个feed) 。你应该找到另一种缓存图像的方法。

答案 1 :(得分:3)

尝试使用SDWebImage,它非常适合在UITableViews中使用来自网络的图片,并为您处理大部分工作。

答案 2 :(得分:0)

最好的想法是缓存图像并使用它们。我已经编写了表视图的代码。 Image on top of Cell 这是一个很好的解决方案。

答案 3 :(得分:0)

尝试使用此代码下载图片

 - (void) downloadThumbnails:(NSURL *)finalUrl
  {
     NSURLRequest* request = [NSURLRequest requestWithURL:finalUrl];
    [NSURLConnection sendAsynchronousRequest:request 
                     queue:[NSOperationQueue mainQueue]
                     completionHandler:^(NSURLResponse * response,
                     NSData * data, NSError * error)
                    {
                      if (!error)
                       {
                      thumbnail = [UIImage imageWithData:data];

                       }       

   }];
 }