UITableView 屏幕图片下载延迟加载 [英] UITableView On Screen Image Download Lazy Loading

查看:31
本文介绍了UITableView 屏幕图片下载延迟加载的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

First of all this is not a duplicate. I have seen some identical questions but they didn't help me as my problem varies a little bit.

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

Using the following code i am download the images asynchronously in my project.

{
    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 服务获取数据后的所有数据.

Due to the logic of the program, i have used the above code in files other than the tableview controller which is showing all the data after getting it from the web service.

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

PROBLEM: On screen images does not show up until i scroll. The off screen images are refreshed first. What can i do to solve my problem.

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

Apple's lazy loading project is using scrollViewDidEndDragging and scrollViewDidEndDecelerating to load the images but the project is way too big to understand plus my code is in files other than the tableview controller.

注意:请不要推荐第三方库,如 SDWebImage 等.

NOTE: Kindly do not recommend third party libraries like SDWebImage etc.

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

UPDATE: As most of people are unable to get the problem, i must clarify that this problem is not associated with downloading, caching and re-loading the images in tableview. So kindly do not recommend third party libraries. The problem is that images are only showing when the user scrolls the tableview instead of loading the on screen ones.

提前致谢

推荐答案

我认为你需要做的是:

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

  1. display some placeholder image in your table cell while the image is being downloaded (otherwise your table will look empty);

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

when the downloaded image is there, send a refresh message to your table.

对于 2,您有两种方法:

For 2, you have two approaches:

  1. 简单的一个:将 reloadData 发送到您的 table view(并检查您的应用程序的性能);

  1. easy one: send reloadData to your table view (and check performance of your app);

发送您的表格查看消息:

send your table view the message:

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

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

Using reloadRowsAtIndexPaths is much better, but it will require you to keep track of which image is associated to which table row.

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

Keep in mind that if you use Core Data to store your images, then this workflow would be made much much easier by integrating NSFetchedResultController with your table view. See here for an example.

另一种方法是使用 KVO:

Again another approach would be using KVO:

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

  1. declare this observe method in 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];
  }
}

}

  • 然后,当您配置单元时:

  • then, when you configure the cell do:

    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];
    

  • 通过这样做,每当给定的item缩略图"键路径发生变化时,cell 都会收到通知.

    By doing this, cell will be notified whenever the given item "thumbnail" keypath changes.

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

    Another necessary change is doing the assignment like this:

           self.thumbnail = [UIImage imageWithData:tempData];
    

    (即,使用 self.).

    另一个

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

    I wanted to download and load the images just like in the LazyTableImages example by Apple. When its not decelerating and dragging, then only onscreen images are loaded, not all images are loaded at once.

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

    I suspect we are talking different problems here.

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

    I thought your issue here was that the downloaded images were not displayed correctly (if you do not scroll the table). This is what I understand from your question and my suggestion fixes that issue.

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

    As to lazy loading, there is some kind of mismatch between what you are doing (downloading the whole feed and then archiving it as a whole) and what you would like (lazy loading). The two things do not match together, so you should rethink what you are doing.

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

    Besides this, if you want lazy loading of images, you could follow these steps:

    1. 不要在parser:foundCDATA:中加载图片,只存储图片网址;

    1. do not load the image in parser:foundCDATA:, just store the image URL;

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

    start downloading the image in tableView:cellForRowAtIndexPath: (if you know the URL, you can use dataWithContentOfURL as you are doing on a separate thread);

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

    the code I posted above will make the table update when the image is there;

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

    at first, do not worry about scrolling/dragging, just make 1-2-3 work;

    一旦它起作用,使用滚动/拖动委托防止在滚动/拖动过程中下载图像(第 2 点);您可以在表格视图中添加一个标志,并让 tableView:cellForRowAtIndexPath: 仅在标志显示无滚动/拖动"时下载图像.

    once it works, use the scrolling/dragging delegate to prevent the image from being downloaded (point 2) during scrolling/dragging; you can add a flag to your table view and make tableView:cellForRowAtIndexPath: download the image only if the flag says "no scrolling/dragging".

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

    I hope this is enough for you to get to the end result. I will not write code for this, since it is pretty trivial.

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

    PS: if you lazy load the images, your feed will be stored on disk without the images; you could as well remove the CGD group and CGD wait. as I said, there is not way out of this: you cannot do lazy loading and at the same time archive the images with the feed (unless each time you get a new image you archive the whole feed). you should find another way to cache the images.

    这篇关于UITableView 屏幕图片下载延迟加载的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

    查看全文
    登录 关闭
    扫码关注1秒登录
    发送“验证码”获取 | 15天全站免登陆