【问题标题】:How to do UITableView operation queues to download concurrentlyUITableView操作队列怎么做并发下载
【发布时间】:2013-03-09 12:32:58
【问题描述】:

我正在做一个 UITableview 来下载数据 webservice 这个名字非常快,所以我最初用它来填充表格,然后我为图像启动了一个操作队列。

然后是其余数据的单独队列,因为它加载非常慢但会影响图像加载时间,我如何同时执行 2 个。

您能找出导致性能下降的原因并帮我解决吗?

【问题讨论】:

    标签: ios objective-c uitableview objective-c-blocks


    【解决方案1】:

    我假设您知道,您可以在创建队列时通过设置maxConcurrentOperationCount 来指定并发请求的数量。四是典型值。

    self.imageDownloadingQueue.maxConcurrentOperationCount = 4;
    

    问题是,你不能比这更大(由于 iOS 限制和一些服务器限制)。可能有 5 个,但不会比这个大。

    就我个人而言,我不会用完有限数量的最大并发操作返回文本值。我会提前检索所有这些。您会延迟加载图像,因为它们太大了,但文本条目太小,以至于执行单独的网络请求的开销开始施加其自身的性能损失。如果您要延迟加载描述,我会分批下载 50 或 100 个左右。

    查看您的源代码,您发出的 JSON 请求至少是您应该发出的两倍(您在 getAnimalRankgetAnimalType 中检索相同的 JSON)。但是你真的应该改变最初的 JSON 请求来返回你需要的一切,名称、等级、类型、URL(但不是图像本身)。然后在一次调用中,您就可以获得所需的一切(除了我们将异步检索的图像,以及您的服务器为 UX 快速交付的图像)。如果您决定保留对排名/类型/url 的各个请求,则需要查看您的服务器代码,因为没有正当理由不应该立即返回,而且目前确实很慢。但是,正如我所说,您真的应该在初始 JSON 请求中返回所有这些内容,这样您的用户界面将会非常快。

    最后一点:您正在使用单独的队列来获取详细信息和图像下载。使用NSOperationQueue 和设置maxConcurrentOperationCount 的全部目的是iOS 只能对给定服务器执行5 个并发请求。通过将它们放在两个单独的队列中,您将失去maxConcurrentOperationCount 的好处。事实证明,请求超时需要一分钟,所以您可能不会遇到问题,但它仍然反映了对队列用途的基本误解。

    归根结底,您应该只有一个网络队列(因为系统限制是您的设备与任何给定服务器之间的网络并发连接数,而不是图像下载量,以及单独下载描述的数量)。

    【讨论】:

      【解决方案2】:

      您是否考虑过异步执行此操作?我写了一个类来做一些与你使用块描述的非常相似的事情。您可以通过两种方式做到这一点:

      1. 只要 cellForRowAtIndexPath 触发就加载异步。这适用于很多情况,但可能会导致错误的图像显示一秒钟,直到正确的图像完成加载。

      2. 在拖动停止时调用进程以加载图像。这通常是我做事的方式,以便正确的图像始终显示它应该显示的位置。在从网络加载图像之前,您可以使用占位符图像。

      查看这个 SO 问题了解详情:

      Loading an image into UIImage asynchronously

      【讨论】:

      • 他是异步执行的。而且您的串行 GCD 队列将比 OP 的 NSOperationQueue 效率更低。
      • 感谢 Rob 的建议。我将使用 NSOperationQueue 进行一些基准测试,看看它有多快。我使用该异步加载类的应用程序有 8000 多条记录数据集为其提供数据,并且速度非常快,但我一直在寻找更好的方法:)
      • 我发现如果我同时下载一堆图像,它的速度会快 25-30%(这将取决于 (a) 图像的大小;以及 (b) 与您的网络连接的延迟)服务器)。您基本上可以减少延迟问题的影响。确保将并发操作限制为 4 个,否则某些操作可能会超时。
      • 关于你的第一点,关于cellForRowAtIndexPath的问题,这通常是两个错误之一的结果:1.未能正确初始化图像之前你发送图像获取对后台队列的更新(从而看到出列单元格的图像;或 2. 在更新图像之前未能仔细检查 cellForRowAtIndexPath。我喜欢您对另一个问题的回答(带有updateCell 警告),我认为cellForRowAtIndexPath 是最好的地方。你的单独课程是优雅的解决方案。干得好。
      • 我收回我之前关于性能差异的评论。我只是看了一眼您的代码(它正在创建一个串行队列),并假设您正在同一个串行队列上进行图像检索。但是您正在为每个图像创建一个单独的串行队列(每个共享相同的名称)!因此,实际上,您没有进行串行操作。我误解了您对串行队列的使用。无论如何,迁移到 NSOperationQueue 不会产生巨大的性能提升,但它会防止出现超时问题,如果您使用您的技术并尝试下载太多图像。
      猜你喜欢
      • 2022-08-08
      • 1970-01-01
      • 1970-01-01
      • 2012-01-09
      • 2013-11-23
      • 2011-02-19
      • 1970-01-01
      • 2018-07-18
      • 2012-06-18
      相关资源
      最近更新 更多