Nsurlsession: How to Increase Time Out for Url Requests

NSURLSession: How to increase time out for URL requests?

ObjC

NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;

Swift

let sessionConfig = URLSessionConfiguration.default
sessionConfig.timeoutIntervalForRequest = 30.0
sessionConfig.timeoutIntervalForResource = 60.0
let session = URLSession(configuration: sessionConfig)

What docs say

timeoutIntervalForRequest and timeoutIntervalForResource specify the timeout interval for the request as well as the resource.

timeoutIntervalForRequest - The timeout interval to use when waiting
for additional data. The timer associated with this value is reset
whenever new data arrives. When the request timer reaches the
specified interval without receiving any new data, it triggers a
timeout.

timeoutIntervalForResource - The maximum amount of time that a
resource request should be allowed to take. This value controls how
long to wait for an entire resource to transfer before giving up. The
resource timer starts when the request is initiated and counts until
either the request completes or this timeout interval is reached,
whichever comes first.

Based on NSURLSessionConfiguration Class Reference

Request Timeout NSURLSession

You can't modify your request because for some reason you went with immutable option. Since NSMutableURLRequest is a subclass of NSURLRequest you can use the very same initializer init(URL:cachePolicy:timeoutInterval:) to create an mutable instance and set default timeout. And then configure (mutate) this request as you need.

let request = NSMutableURLRequest(URL: url!, cachePolicy: .ReloadIgnoringLocalAndRemoteCacheData, timeoutInterval: 5.0)

NSURLSession sharedSession default timeout

There are two timeouts for URL sessions. The first is the maximum time allowed between receiving new data. This is called the timeoutIntervalForRequest. The second is the maximum time the entire request is allowed to take (assuming it's regularly receiving new data). This is called the timeoutIntervalForResource.

Both of these timeouts are configured by default using NSURLSessionConfiguration, and can be overridden on the NSURLRequest.

The default timeoutIntervalForRequest is 60 seconds.

The default timeoutIntervalForResource is 7 days.

NSURLSession set request timeout accurately

It can be used, but it rarely makes sense to do so.

The expected user experience from an iOS app is that when the user asks to download or view some web-based resource, the fetch should continue, retrying/resuming as needed, until the user explicitly cancels it.

That said, if you're talking about fetching something that isn't requested by the user, or if you are fetching additional optional data that you can live without, adding a resource timeout is probably fine. I'm not sure why you would bother to cancel it, though. After all, if you've already spent the network bandwidth to download half of the data, it probably makes sense to let it finish, or else that time is wasted.

Instead, it is usually better to time out any UI that is blocked by the fetch, if applicable, but continue fetching the request and cache it. That way, the next time the user does something that would cause a similar fetch to occur, you already have the data.

The only exception I can think of would be fetching video fragments or something similar, where if it takes too long, you need to abort the transfer and switch to a different, lower-quality stream. But in most apps, that should be handled by the HLS support in iOS itself, so you don't have to manage that.

NSURLSession timeout

You cannot change the timeout on the sharedSession or a sessions configuration property. You have to set the timeout when the session is created. See this for an example of how to create a session and its timeout: https://stackoverflow.com/a/30427187/78496

Handle URLSession timeout

You can cast your error to URLError type and then use the code property to safely check if it's a session timeout error:

if (err as? URLError)?.code == .timedOut {
// Handle session timeout
}

Can't catch Time out error using URLSession

Printing the rawValues of all the possible URLError codes:

unknown: -1
cancelled: -999
badURL: -1000
timedOut: -1001
unsupportedURL: -1002
cannotFindHost: -1003
cannotConnectToHost: -1004
networkConnectionLost: -1005
dnsLookupFailed: -1006
httpTooManyRedirects: -1007
resourceUnavailable: -1008
notConnectedToInternet: -1009
redirectToNonExistentLocation: -1010
badServerResponse: -1011
userCancelledAuthentication: -1012
userAuthenticationRequired: -1013
zeroByteResource: -1014
cannotDecodeRawData: -1015
cannotDecodeContentData: -1016
cannotParseResponse: -1017
appTransportSecurityRequiresSecureConnection: -1022
fileDoesNotExist: -1100
fileIsDirectory: -1101
noPermissionsToReadFile: -1102
dataLengthExceedsMaximum: -1103
secureConnectionFailed: -1200
serverCertificateHasBadDate: -1201
serverCertificateUntrusted: -1202
serverCertificateHasUnknownRoot: -1203
serverCertificateNotYetValid: -1204
clientCertificateRejected: -1205
clientCertificateRequired: -1206
cannotLoadFromNetwork: -2000
cannotCreateFile: -3000
cannotOpenFile: -3001
cannotCloseFile: -3002
cannotWriteToFile: -3003
cannotRemoveFile: -3004
cannotMoveFile: -3005
downloadDecodingFailedMidStream: -3006
downloadDecodingFailedToComplete: -3007
internationalRoamingOff: -1018
callIsActive: -1019
dataNotAllowed: -1020
requestBodyStreamExhausted: -1021
backgroundSessionRequiresSharedContainer: -995
backgroundSessionInUseByAnotherProcess: -996
backgroundSessionWasDisconnected: -997

You can see that you are looking for notConnectedToInternet code. (the one with rawValue -1009)

So, your code might look like this:

switch (err as? URLError)?.code {
case .some(.timedOut):
// Handle session timeout
case .some(.notConnectedToInternet):
// Handle not connected to internet
default: break
}

URLSession dataTask timeout error

Timeouts should always several minutes long, not twenty seconds. It can take twenty or thirty seconds just to do a DNS lookup on a bad cellular connection, and using a twenty-second timeout means that on a poor network, your app will be completely unusable.

The way you handle this in the UI should be entirely independent of the networking code. Start the request and simultaneously create and start a timer. If your session delegate hasn't gotten a ...didReceiveResponse:... call by the time the timer fires, show a "slow network" UI, but let the network request continue until it fails.

Additionally, if your requests are idempotent (that is, if issuing the request twice is safe), you might consider having a second timer with a very short interval (say 5 seconds), and if you haven't gotten a didReceiveResponse: call within that time, start a second request in parallel. If that second task doesn't get a response by the time your twenty-second timer fires, cancel it. If it gets a response first, cancel the original request. This can help reduce the impact of packet loss on user-perceived latency.

NSURLSessionDataTask timeout subsequent requests failing

I didnt see you resume the task you started. You need to declare:

[task resume];

This line Resumes the task, if it is suspended.

Try to call the NSURLSession as follows:

[NSURLSession sharedSessison] instead of self.session

and invalidate the session by:

 [[NSURLSession sharedSession]invalidateAndCancel];

From Apple's Documentation:

When your app no longer needs a session, invalidate it by calling either invalidateAndCancel (to cancel outstanding tasks) or finishTasksAndInvalidate (to allow outstanding tasks to finish before invalidating the object).

    - (void)invalidateAndCancel

Once invalidated, references to the delegate and callback objects are
broken. Session objects cannot be reused.

To allow outstanding tasks to run until completion, call finishTasksAndInvalidate instead.

  - (void)finishTasksAndInvalidate

This method returns immediately without waiting for tasks to finish. Once a session is invalidated, new tasks cannot be created in the session, but existing tasks continue until completion. After the last task finishes and the session makes the last delegate call, references to the delegate and callback objects are broken. Session objects cannot be reused.

To cancel all outstanding tasks, call invalidateAndCancel instead.



Related Topics



Leave a reply



Submit