25

With the new NSURLSession, there is now a timeoutIntervalForRequest on the NSURLSessionConfiguration object used to create the session.

But there is still a timeoutInterval on the NSURLRequest object that can be used to create the NSURLSessionTask in the session.

My question is, if the configuration has a timeoutIntervalForRequest set to 30, but the NSURLRequest use to create the task has a timeoutInterval of 60, which timeout interval will actually be used?

Utsav Dusad
  • 2,139
  • 4
  • 31
  • 52
Joe Licari
  • 768
  • 1
  • 8
  • 6

4 Answers4

23

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.

n-miyo
  • 346
  • 3
  • 4
  • Hi, your answer sends me in the right direction. It made me realize that timeoutIntervalForRequest and timeoutIntervalForResource should be used. However, I can't seem to ever see any callbacks being called after the timeout delay when using NSURLSessionDownloadTask in background. Which callback is called with you get timeout? Is it still URLSession:task:didCompleteWithError: ? – Thibault D. Apr 25 '14 at 08:35
  • Ok, it looks like it works when not using background sessions... But does not work when using background sessions... – Thibault D. Apr 25 '14 at 08:43
  • i want the time out interval of my web services to be 180 seconds(3 min).Since i read about NSURLSESSION and its timeoutIntervalForRequest and timeoutIntervalForResource, i tried using these, which again yielded same results as timeOutInterval of NSMutableURLRequest.i.e., i am setting time out interval of 180 seconds like sessionConfig.timeoutIntervalForRequest = 180.0; sessionConfig.timeoutIntervalForResource = 180.0; but i am receiving failure call back in 75 seconds or at some random time interval, saying 'The request timed out'. Have any idea on this? – XiOS Dec 17 '14 at 05:19
  • Is it actually like we could set time outs only for background processes? – XiOS Dec 17 '14 at 05:20
  • hi @XiOS, do you find the solution of maximum timeout of not more than 75 seconds? – Pranjal Bikash Das Jan 22 '16 at 09:25
  • 2
    The timer of `timeoutIntervalForRequest` is reset whenever data arrives, no matter how much data (just a single byte arriving would reset it), it only causes a timeout if absolutely no data arrives for this interval. The timer for `timeoutIntervalForResource` is never reset, it produces a timeout unless the task fully completed as that will stop that timer from firing. – Mecki Feb 21 '19 at 11:19
5

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.

Utsav Dusad
  • 2,139
  • 4
  • 31
  • 52
  • 1
    I'm using NSURLSession to check whether a given url is still active or broken, any recommendation on what time I should set `timeoutIntervalForResource` to? My goal is to set it so that its the absolute minimum time needed to determine if the url is active or not? – GarySabo Feb 16 '16 at 00:35
  • 1
    In my experiments, if you set `timeoutInterval` to something like 15 seconds for `NSURLRequest` and `NSURLSession` is a background session, iOS will keep retrying approx. every 15 seconds up until `timeoutIntervalForResource` is reached. It will be happening, of course, if iOS thinks that your network is good. No callback will be called - it's true. Tested on iOS 9.2/ – mutable.me Mar 02 '16 at 02:59
  • @GarySabo: I think for that you should use reachability module. – Utsav Dusad Mar 02 '16 at 05:00
5

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.

Mecki
  • 125,244
  • 33
  • 244
  • 253
2

Looks like things changed since n-miyo tested it.

The apple documentation states the NSURLRequest value will override the session configuration.

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. For example, if the session configuration specifies that cellular networking should not be allowed, the NSURLRequest object cannot request cellular networking.

Zeev Vax
  • 914
  • 7
  • 13