GarySabo
GarySabo

Reputation: 6680

Cancel NSURLSession dataTask when request is taking too long

On certain websites the below method hangs indefinitely, I'd like to cancel the request when its taking too long, I thought that timeoutIntervalForRequest and timeoutIntervalForResource would control this but setting either of them doesn't seem to have any effect.

This is an example website that the request hangs indefinitely on: http://www.samtoft.co.uk/showpic.php?id=542&order=&search=#header

// fetch data from URL with NSURLSession
    class func getDataFromServerWithSuccess(myURL: String, noRedirect: Bool, callback: Result<String> -> Void) {

        var loadDataTask: NSURLSessionDataTask? = nil
        let sessionConfig: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()

        sessionConfig.timeoutIntervalForRequest = 10.0
        sessionConfig.timeoutIntervalForResource = 10.0

        var myDelegate: MySession? = nil
        if noRedirect {
            myDelegate = MySession()
        }

        let session = NSURLSession(configuration: sessionConfig, delegate: myDelegate, delegateQueue: nil)
        loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in


                if let checkedData = data {

                let success = Result.Success(NSString(data: checkedData, encoding: NSASCIIStringEncoding) as! String)


                callback(success)

                } else {

                    let redirectError = NetworkError.FailedUrl("\(myURL) + \(error)")


                    if let request = loadDataTask?.currentRequest {

                        guard let urlExtension = request.URL?.pathExtension else {return}
                        guard let domain = request.URL?.host else {return}



                        guard let finalURLAsString = request.URL?.description else {return}
                        let failure = Result.Failure("\(finalURLAsString) + \(redirectError)") 
                            callback(failure)

                    }

                }
        }
        loadDataTask!.resume()


    }

EDIT: for anyone who is having the same issue I was, the problem was that I was accounting for the success case and the error case, but not for when the request returned no response, so I added the below:

if response == nil {
                print("NO RESPONSE \(myURL)")
                let noResponse = Result.NoResponse("NO RESPONSE") 
                callback(noResponse)
            }

Upvotes: 2

Views: 1344

Answers (1)

James Rao
James Rao

Reputation: 170

I have extracted your code as

func getDataFromServerWithSuccess(myURL: String) {
    var loadDataTask: NSURLSessionDataTask? = nil
    let sessionConfig: NSURLSessionConfiguration = NSURLSessionConfiguration.defaultSessionConfiguration()

    //sessionConfig.timeoutIntervalForRequest = 11.0
    sessionConfig.timeoutIntervalForResource = 11.0

    let session = NSURLSession(configuration: sessionConfig)
    loadDataTask = session.dataTaskWithURL(NSURL(string: myURL)!) { (data: NSData?, response: NSURLResponse?, error: NSError?) -> Void in

        print("end")
    }

    loadDataTask!.resume()
}

It does work sensitively for the timeout. I suppose there may be something wrong with the delegator which cannot receive the response properly. Hope this helps.

Upvotes: 1

Related Questions