NSURLSessionTask. Suspend does not work
Asked Answered
I

3

9

This is what Apple's documentation says regarding suspend method of NSURLSessionTask class

A task, while suspended, produces no network traffic and is not subject to timeouts.

Ok. So I'm running the following simple code:

        let url   = NSURL(string: "http://httpbin.org/delay/10")!
        let urlRequest = NSURLRequest(URL: url)

        self.task = NSURLSession.sharedSession().dataTaskWithURL(urlRequest.URL!, completionHandler: {

            data, response, error in print("completion ERROR \(error)")
        })

        self.task.resume()

        print("Start")
        delay(5, closure: {

            self.task.suspend()

            print("Suspend")
        })

Function delay is simply a wrapper around dispatch_after and a request to http://httpbin.org/delay/10 gives response after 10 seconds. In the middle of waiting for response I suspend the task. However that does not work. In 60 seconds the completion block is called with timeout error. Can anybody please explain what's wrong?

Inspector answered 17/11, 2016 at 18:5 Comment(1)
Can you show the wrapper around dispatch_after?Corposant
C
8

This appears to be normal behaviour, however more definitive documentation from Apple would be useful in clarifying what we are seeing.

Apple’s documentation does not provide a detailed explanation of how suspend works, or when it should be used. However, my view (based on testing and research) is that suspend() should only be used for download tasks. Data tasks should only use resume() (to start the task) and cancel() when appropriate.

My testing, using Xcode and Charles Proxy, revealed a suspended data task has no effect on the network traffic as indicated in Apple’s documentation. In other words, network traffic is produced.

I observed two things using suspend and data tasks:

1) If it's called right after resume, it has no effect on the data task. It does not suspend network traffic and barring no network or server side-side issues, a successful response is received in the callback.

2) If it's called in the dispatch.asyncAfter callback, it still does not suspend the network traffic, however the callback gets a “request timeout” error instead of a successful response. According to Charles Proxy, the request is successful though. It is this result that leads me to believe that suspend() should not be be used with data tasks. The result of this callback is essentially useless in my opinion.

Cancelling a data task:

cancel() works as expected. The client (you) closes the connection before getting a complete response from the server. This can be done right after calling resume() or at a later time (before the request has completed of course).

Corposant answered 17/11, 2016 at 19:36 Comment(3)
"The request timed out."? What is that? The error passed into the completion block? So it works for you just like for me, therefore it is normal behaviour for a suspended task, right? If yes, then why do we need suspend at all? Or did I misunderstand something?Inspector
@AndreyChernukha Sorry, it seems I misinterpreted your question. I thought you were not seeing the “Suspend” message in the console.Corposant
@AndreyChernukha You are right, I have updated my answer to provide more details. It appears to be normal behaviour for a data task. A download task would presumably not get passed to the completion block until the task is resumed and completed.Corposant
P
0

I accept that suspend() has no effect on URLSessionDataTask

                    let dataTask = URLSession.shared.dataTask(with: request) { (data, urlResponse, error) in                        
                    print("response is received all the time")
                    }
                }
                dataTask.resume()
                dataTask.suspend()

However when I try cancelling it does

let dataTask = URLSession.shared.dataTask(with: request) { (data, urlResponse, error) in                        
                    print("response is cancelled")
                    }
                }
                dataTask.resume()
                dataTask.cancel()
Panicle answered 17/2, 2017 at 10:47 Comment(0)
V
0

You can call dataTask with URLRequest and set timeoutInterval to .infinity. (default is 60s)

var request = URLRequest(url: url)
request.timeoutInterval = .infinity
task = session.dataTask(with: request)
task?.resume()
Vibrio answered 11/4, 2022 at 6:9 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.