【问题标题】:Should my model objects be responsible for downloading their own resources?我的模型对象是否应该负责下载自己的资源?
【发布时间】:2013-11-25 20:13:10
【问题描述】:

Myapp 使用远程 API 来更新其数据,并且它必须离线工作,因此在显示应用程序的主要部分之前必须下载所有数据。

API 返回一个代表应用内容的大型 JSON 结构。 JSON 被转换为许多字典和数组,然后模型类被实例化并由这些字典和数组支持。

我的问题是其中一些字典和数组包含还必须下载的图像的 URL。每个模型对象是否应该负责下载自己的图像?或者我应该有某种控制器类来处理这个?

另外,处理这个问题的好方法是什么?例如,我如何知道所有模型对象何时完成下载资源?

所有资源必须预先上传,因为客户希望能够在没有互联网连接的情况下使用该应用程序。

【问题讨论】:

  • 这取决于许多因素。不可能有一个普遍的答案。您是否想要/需要预缓存,或者这不可能?每个图像有多大?您是否同时有其他并发且可能更重要的请求?...
  • 并不是说这是题外话,但这是"whiteboard" -- as opposed to "keyboard" 的那种问题——可能更适合Software Engineering 的问题。只是未来的一种选择。
  • 没有。模型对象(实际上称为 domain objects 不应该负责存储自己。这将违反 SRP

标签: ios model-view-controller


【解决方案1】:

答案取决于您应用的业务需求。

  1. 通常会预先下载 JSON 数据,但会延迟加载图像,直到 UI 需要时才下载它们(一种称为“延迟加载”的模式)。一种特别优雅的处理方式是使用执行即时异步图像检索的UIImageView 类别(SDWebImage 是一个非常好的实现;如果您使用的是AFNetworking,它也有一个) .对于这两种情况,您只需执行以下操作:

    [self.imageView setImageWithURL:url];
    

    这将异步检索图像,缓存图像以防您的 UI 再次需要它等等。此外,如果您在具有单元重用的 tableview 中使用它,它将取消对先前已下载单元格的旧请求'尚未完成,以确保对可见单元格图像的请求不会积压在用户可能不再关心的一堆旧请求之后,等等。

  2. 但有时,您确实希望预先检索所有内容(例如,您正在下载一本杂志的内容,以供离线阅读)。

    在这种情况下,您可能有一个单独的数据控制器来下载和解析结果,而不是让模型本身进行检索。如果您需要在完成此操作时通知 UI,您可以使用本地通知来执行此操作。

虽然后一种模式乍一看似乎很吸引人,但它有许多缺点。例如,如果用户使用蜂窝连接,您可能会花费大量带宽下载用户可能不会立即需要的图像,在此过程中消耗用户的数据计划和电池。因此,您可能只想在以下情况下执行此操作: (a) 您确实需要预先准备好所有内容以供离线使用;并且 (b) 您可以接受这需要消耗的资源(数据计划和电池消耗)。

【讨论】:

  • 嗨 Rob,它必须是后者。我习惯使用您建议的第一种方法,但客户端要求预先下载所有内容,然后该应用程序将主要在没有连接的情况下使用。我只是不确定如何监控所有图像的异步下载以及如何知道它们何时完成下载。
  • @DarrenFindlay:你能把图片服务器端打包成一个存档吗?
  • @DarrenFindlay 我个人会使用基于NSOperation 的下载机制(要么自己滚动(like this),要么更好地使用AFNetworking),然后创建最终的“completionOperation”它对所有单独的下载都有依赖关系,下载完成后,您的“completionOperation”将启动。
【解决方案2】:

您可能需要一个下载管理器类(与您的模型分开)来负责下载图像。您的管理器类将管理操作的操作队列,每个操作都下载给定模型对象的资产。使用AFNetworking 将使这一切变得非常简单。然后,您可以在后台运行这些操作,让您的用户在下载时继续使用 UI。

您的下载管理器将创建一个AFHTTPClient,循环访问您的模型,创建一个AFImageRequestOperations 数组,每个模型一个(或每个下载一个,如果每个模型有多个图像)。将您的操作数组传递给 HTTP 客户端上的 enqueueBatchOfHTTPRequestOperations: progressBlock: completionBlock:。当所有下载操作完成后,您的完成块将被调用。

从 JSON 获得所有模型后,应运行此下载过程,以确保您拥有获取所有资产所需的所有数据。

编辑:值得注意的是,如果您只支持 iOS 7,AFNetworking 的AFHTTPSessionManager 会更合适。我提供的建议适用于 iOS 7,也支持 iOS 6。

【讨论】:

  • 请注意,您指的是 AFNetworking 1.0,而不是更新的 AFNetworking 2.0
  • @vikingosegundo 感谢您指出这一点。我的代码仍然支持 iOS 6,所以我无法迁移到 2.0
  • 感谢您不发狂地评论您的回答 :)
猜你喜欢
  • 2013-06-24
  • 1970-01-01
  • 1970-01-01
  • 2021-02-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-04-12
相关资源
最近更新 更多