Using OperationQueue for your URL requests (with a built-in retry mechanism).
Here is the detailed lifespan of an
First, the URL is processed for running. Which means the method
processURLRequestForRunning is called. This is an override point for
subclasses if they want to prevent the request to run depending on certain
condition, or if they want to modify the URL Request prior running it.
This processing might take some time, or be expensive resource-wise, which
is why you can specify a queue on which the processing will be done. (This
If the processing fails (returns an error), the operation will go to the error processing step (4) with the given error (the operation might be retried later depending on the error processing result).
Next, the session task is created. The creation of the task and the behavior of the operation will differ depending on the delegate of the URL session given to the operation.
Session delegate is an instance of
The task is created with
(which can be overridden if need be). By default, in this method, the
session delegate is told to forward the delegate method regarding this
specific task to the operation (the delegate of an URL session is a
global delegate and cannot be set by task without this hack AFAIK).
If subclasses overwrite this method and decide to work a different way
for the delegate method, they will be responsible for receiving the data
and treating it, then must call
urlSession(_:task:didCompleteWithError:) when the task is done.
Session delegate is kind of another class of
nil: The task is created
Finally the task is launched.
errorForResponse(_:)will check whether the response is appropriate (correct status code and mime type, or other pre-filters). Then the
urlResponseProcessorwill be called if the previous check passes. Both method can cancel the session task if they deem the response not worthy of continuing.
urlSession(_:task:didCompleteWithError:)), the task will finish.
processEndOfTask(error:)(private) is called to check what to do from here.
If there is already a final error (eg. operation cancelled), the operation is ended here.
computeRetryInfo(sourceError:completionHandler:) method is
called on the
queueForComputingRetryInfo (computing the retry info might
be an expensive operation). This method is reponsible for telling whether
the operation should be retried, and after which delay. The default
implementation will check the error. For a network lost for instance, the
operation should be retried for idempotent HTTP requests. The delay
respects an exponential backoff by default. Subclasses can override to
implement their own logic and behavior.
This is actually the most important override point for the operation.
computeRetryInfo method will also allow to decide whether some “early
retrying” techniques should be setup. Or you can setup your own. There are
two built-in retrying techniques: The
ReachabilityObserver which will
simply check when the network is reachable again and the
Other Success Observer which will trigger a retry when another URLRequestOperation for
the same host succeeds.
If you decide to write your own “early retrying” methods, you should
removeObserverForEarlyRetrying() and remove your observers in
your implementation. Do not forget to call super!
If the operation is told to be retried, when it is retried, we simply go back to step 2. (The URL is re-processed, etc.)
|Last commit: Yesterday|