NSURLSessionTask. Suspend does not work

2019-06-20 23:06发布

问题:

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?

回答1:

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).



回答2:

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()