【问题标题】:Best way to ensure an initial network request is completed before other requests are sent (iOS app)确保在发送其他请求之前完成初始网络请求的最佳方法(iOS 应用程序)
【发布时间】:2017-02-19 21:19:08
【问题描述】:

我正在开发的应用程序需要在服务器上创建一个容器对象并将项目插入该容器。在需要插入第一项之前,我不想创建容器对象。但是,创建容器对象需要一些初始化,这可能需要一些时间。当该容器仍在初始化时,用户仍然可以发送由于容器尚未准备好而未得到处理的插入请求。我有两个主要问题:

  1. 应该在客户端还是服务器端处理?
  2. 处理此类问题的最佳做法是什么?

基本上,在发送任何insertItem 请求之前,我需要确保我的初始createContainer 数据任务完成。

补充信息

通过单击相应的tableViewCell 发送insertItem 请求。用户单击的第一个tableViewCell 发送一个createContainer 请求,该请求创建一个包含第一个项目的容器。

对于包含 n 个项目的容器,请求应按以下顺序发送:

  • createContainer(Container(with: item1)
  • insertItem(item2)
  • ...
  • insertItem(itemn)

第一个请求完成后,剩余的 n – 1 个请求可以按任意顺序完成。

我的想法

听起来我希望同步处理 createContainer 请求,而应该异步处理 insertItem 请求。我不确定这是否是最好的方法,甚至不确定如何适当地执行,所以任何指导将不胜感激。

【问题讨论】:

    标签: ios swift networking


    【解决方案1】:

    您可以使用NSOperationQueue 和多个NSOperations 来实现您想要的行为。一个NSOperation 实例可以依赖于另一个NSOperation 实例的完成:

    依赖关系

    必须完成的操作对象数组 在当前对象开始执行之前执行。

    对于您的示例,这意味着 insertItem-Operations 依赖于 createContainer 操作。

    当您将所有这些操作添加到 NSOperationQueue 时,您的 createContainer 操作将首先运行。完成后,其他操作将开始运行,因为它们的依赖关系现在已满足。您还可以在NSOperationQueue 上使用maxConcurrentOperationCount 控制要同时运行的操作数。

    由于您将在 NSOperations 中使用异步 API,因此您需要实现 ConcurrentOperation 并自己处理状态更改。 API 参考非常详细地解释了这一点。

    查看API Reference for NSOperation 了解更多信息。 还有一个不错的NSHipster article on NSOperations

    【讨论】:

    • 虽然这个答案确实让我找到了我需要的解决方案,但它并不完全适合我的用例。事实证明,当一个createContainer 请求开始时——但在响应返回之前——用户发起了更多的insertItem 请求,这需要createContainer 完成。 OperationQueues 是必需的,但必须以不同的方式处理依赖关系。任何其他人在寻找此用例的描述,请参阅this article
    • 我认为你应该实现一个并发操作而不是使用信号量。有关如何做到这一点,请参阅以下要点:gist.github.com/calebd/93fa347397cec5f88233 并发操作需要您手动处理状态更改。一旦网络请求完成,您可以将状态设置为.finished。这样您就可以使用NSOperations 来管理网络请求的依赖关系。
    • 我明白了,这当然是一个更好的解决方案。然后我会将createContainer 设为ConcurrentOperation 并让insertItems 成为传统的Operations,因为在createContainer 完成后我不需要跟踪任何内容?然后我会将这些操作放在同一个OperationQueue 中吗? ConcurrentOperation 中的 Swift 3 version 的行为是否相同?
    • 你是否应该使用ConcurrentOperation并不取决于你是否想在操作完成后做某事。这取决于您在操作中使用的 API 本身是否是异步的(如网络请求)。对于任何同步的ConcurrentOperation 也可以工作,但您并不真正需要增加的复杂性。只需使用常规的NSOperation 并实现- main。是的,在您的情况下,您应该将您的操作添加到相同的OperationQueue
    • 您链接到的 Swift 3 版本似乎工作正常。我还可以推荐PSOperations 来进行一些高级添加。我不会只为ConcurrentOperations 添加它,但如果您需要其他功能(例如GroupOperation),它可能是一个不错的添加。
    【解决方案2】:

    除了 NSOperationQueue 答案之外,有时很难手动管理 NSOperation 处理诸如网络调用之类的异步事件所需的所有 状态更改

    为了简化这一点,您可以使用名为 Overdrive 的 Swift 库。这是一个了不起的库,您可以在其中简单地继承 Task 类并在 run() 函数中编写网络代码。完成后,您只需调用 self.finish 即可完成任务。这是一个示例:只需创建一个简单的下载任务:

    然后,只需将其添加到队列中。

    还可以在任务之间添加依赖,基本解决了你的用例。

    希望这会有所帮助。

    【讨论】:

    • 哇,这是很多很好的信息。一定会有所帮助,感谢您的贡献。
    猜你喜欢
    • 1970-01-01
    • 2011-06-16
    • 1970-01-01
    • 2023-03-24
    • 2013-08-11
    • 1970-01-01
    • 1970-01-01
    • 2022-11-28
    • 2015-08-11
    相关资源
    最近更新 更多