NSURLSessionConfiguration timeoutIntervalForRequest vs NSURLSession timeoutInterval
As my investigation on iOS 7.0.3, timeoutInterval
for NSURLRequest
does not get any effects when it is used with NSURLSession
.
Whether you set timeoutIntervalForRequest
for NSURLSessionConfiguration
or not, timeoutInterval
is just ignored.
You can use my tiny sample application NetworkTimeoutSample for checking this behavior.
When you set 1 for 'URLReq' field, which affects timeoutInterval
for NSURLRequest
, then click 'NSURLSession With URLRequest' button, your session will not get timeout error.
You also may recognize you should set timeoutIntervalForResource
, instead of timeoutIntervalForRequest
for NSURLSession
if you'd like to get same timeout effect for timeoutInterval
of NSURLRequest
.
If you set both timeoutIntervalForRequest
and timeoutIntervalForResource
value for NSURLSessionConfiguration
, smaller value will be affected(I feel this behavior is different from current API document).
There are no documentation about those specifications, so it might be changed on future iOS version.
Since iOS8, the NSUrlSession in background mode does not call this delegate method if the server does not respond. -(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error
The download/upload remains idle indefinitely. This delegate is called on iOS7 with an error when the server does not respond.
In general, an NSURLSession background session does not fail a task if something goes wrong on the wire. Rather, it continues looking for a good time to run the request and retries at that time. This continues until the resource timeout expires (that is, the value of the timeoutIntervalForResource property in the NSURLSessionConfiguration object you use to create the session). The current default for that value is one week! In other words, the behaviour of failing for a timeout in iOS7 was incorrect. In the context of a background session, it is more interesting to not fail immediately because of network problems. So since iOS8, NSURLSession task continues even if it encounters timeouts and network loss. It continues however until timeoutIntervalForResource is reached.
So basically timeoutIntervalForRequest won't work in Background session but timeoutIntervalForResource will.
I got this answer from one of the members of Apple Staff at the developer forum. Also, I have verified this by implementing.
NSURLSession
offers two timeouts, timeoutIntervalForRequest
and timeoutIntervalForResource
.
timeoutIntervalForRequest
is enforced by a timer that is reset every time data is transferred. So if you set this timeout to 30 seconds and at least one byte of data is transferred every 30 seconds, the timeout is never hit. The timeout is only hit if absolutely no data is transferred for 30 seconds. You could also say that this is the maximum idle time for a session task. The default value is 60 seconds.
timeoutIntervalForResource
is enforced by a timer that is never reset. It is started when a session task is started and it is stopped when a session task is stopped or has finished. So this is the maximum total amount of time a session task can take and this is what most people think of, when they hear "timeout". As a session task may also be a download of a 100 GB file over a very slow Internet link, the default value here is 7 days!
NSURLRequest
(and its mutable subclass) offers only one property timeoutInterval
. This timeout value behaves like timeoutIntervalForRequest
as the documentation of NSURLRequest
says:
If during a connection attempt the request remains idle for longer than the timeout interval, the request is considered to have timed out.
Source: timeoutInterval - NSURLRequest | Apple Developer Documentation
And the documentation of NSURLSession
says:
Note
In some cases, the policies defined in this configuration may be overridden by policies specified by an NSURLRequest object provided for a task. Any policy specified on the request object is respected unless the session’s policy is more restrictive.
Source: NSURLSessionConfiguration - Foundation | Apple Developer Documentation
So the timeoutInterval
of a NSURLRequest
would override the timeoutIntervalForRequest
of a NSURLSession
but only if it is considered to be "more restrictive" by the system, otherwise the value of NSURLSession
will win.