2

首先,这不是重复的。我看到了一些相同的问题,但它们对我没有帮助,因为我的问题略有不同。

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

{
    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 中的图像无关。所以请不要推荐第三方库。问题是图像仅在用户滚动表格视图而不是加载屏幕视图时显示。

提前致谢

4

4 回答 4

4

我认为你需要做的是:

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

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

对于 2,您有两种方法:

  1. 简单的一个:发送reloadData到您的表格视图(并检查您的应用程序的性能);

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

    - (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation
    

使用reloadRowsAtIndexPaths要好得多,但它需要您跟踪哪个图像与哪个表格行相关联。

NSFetchedResultController请记住,如果您使用 Core Data 来存储图像,那么通过与表格视图集成,这个工作流程会变得更加容易。有关示例,请参见此处

另一种方法是使用 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];
    

通过这样做,每当给定的“缩略图”键路径更改cell时都会收到通知。item

另一个必要的改变是做这样的分配:

       self.thumbnail = [UIImage imageWithData:tempData];

(即,使用self.)。

另一个编辑:

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

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

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

至于延迟加载,您正在做的事情(下载整个提要,然后将其作为一个整体存档)与您想要的(延迟加载)之间存在某种不匹配。这两件事不匹配,所以你应该重新考虑你在做什么。

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

  1. 不加载图片parser:foundCDATA:,只存储图片URL;

  2. 开始下载图像tableView:cellForRowAtIndexPath:(如果您知道 URL,则可以使用 dataWithContentOfURL ,就像在单独的线程上一样);

  3. 我在上面发布的代码将在图像存在时更新表格;

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

  5. 一旦它工作,使用滚动/拖动代理来防止在滚动/拖动期间下载图像(第 2 点);您可以在表格视图中添加标志并 tableView:cellForRowAtIndexPath:仅在标志显示“禁止滚动/拖动”时才下载图像。

我希望这足以让您获得最终结果。我不会为此编写代码,因为它非常简单。

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

于 2013-03-08T10:47:20.050 回答
3

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

于 2013-03-08T09:47:49.220 回答
0

最好的办法是缓存图像并使用它们。我已经编写了表格视图的代码。 细胞顶部的图像 这是一个很好的解决方案。

于 2013-03-08T09:54:28.487 回答
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];

                       }       

   }];
 }
于 2013-03-08T09:57:08.063 回答