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.