使用 OperationQueue 处理 URL 请求 (带有内置的重试机制)。
以下是 URLRequestOperation
的详细生命周期
首先,URL 会被处理以便运行。这意味着会调用 processURLRequestForRunning
方法。 如果子类想要阻止请求根据某些条件运行,或者如果他们想要在运行之前修改 URL 请求,这是一个重写点。
这个处理可能需要一些时间,或者消耗大量的资源,这就是为什么你可以指定一个队列来完成处理。(这就是 queueForProcessingURLRequestForRunning
属性。)
如果处理失败(返回一个错误),操作将会进入错误处理步骤 (4),并带有给定的错误(操作可能会在之后重试,取决于错误处理结果)。
接下来,会创建会话任务。任务的创建和操作的行为会因为传递给操作的 URL 会话的代理而有所不同。
会话代理是一个 URLRequestOperationSessionDelegate
的实例:使用 urlSessionTaskForURLRequest(_:withDelegate)
创建任务 (如果需要可以被重写)。 默认情况下,在此方法中,会通知会话代理将关于此特定任务的代理方法转发给该操作(URL 会话的代理是一个全局代理,并且没有此技巧 AFAIK 就不能通过任务设置)。
如果子类重写此方法并决定以不同的方式处理代理方法,他们将负责接收和处理数据,然后**必须**在任务完成时调用 urlSession(_:task:didCompleteWithError:)
。
会话代理是另一种类型的 nil
:使用 urlSessionTaskForURLRequest(_:,withDataCompletionHandler:, downloadCompletionHandler:)
创建任务。
最后,任务被启动。
URLRequestOperationSessionDelegate
的实例时errorForResponse(_:)
方法会检查响应是否合适(正确的状态代码和 MIME 类型或其他预过滤器)。 如果之前的检查通过,则会调用 urlResponseProcessor
。 如果他们认为响应不值得继续,这两种方法都可以取消会话任务。urlSession(_:task:didCompleteWithError:)
),任务将完成。 调用 processEndOfTask(error:)
(私有)来检查接下来该怎么做。processEndOfTask(error:)
。processEndOfTask(error:)
)如果已经存在最终错误(例如,操作被取消),则在此处结束操作。
否则,会在 queueForComputingRetryInfo
上调用 computeRetryInfo(sourceError:completionHandler:)
方法(计算重试信息可能是一个开销很大的操作)。 此方法负责告知是否应重试操作,以及在哪个延迟之后重试。 默认实现将检查错误。 例如,对于网络丢失,对于幂等的 HTTP 请求应重试该操作。 默认情况下,延迟遵循指数退避。 子类可以重写以实现他们自己的逻辑和行为。 这实际上是该操作最重要的重写点。
computeRetryInfo
方法还将允许决定是否应设置一些“提前重试”技术。 或者您可以设置您自己的技术。 有两种内置的重试技术:ReachabilityObserver
,它将简单地检查网络何时再次可达,以及 Other Success Observer
,当另一个针对相同主机的 URLRequestOperation 成功时,它将触发重试。
如果您决定编写您自己的“提前重试”方法,您应该重写 removeObserverForEarlyRetrying()
并在您的实现中删除您的观察者。 不要忘记调用 super!
如果操作被告知要重试,当它被重试时,我们只需回到步骤 2。(URL 被重新处理,等等。)
这个项目最初由 François Lamboley 在 happn 工作时创建。